Compare commits
380 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 992458ae4b | |||
| 8c16686150 | |||
| 7cbadfbd12 | |||
| 0e43697ee0 | |||
| 7de27df309 | |||
| b06db1ba39 | |||
| 5fe24cb689 | |||
| 733d1384a4 | |||
| 99e9d0d023 | |||
| 2bd1e46ab9 | |||
| cabaad4b17 | |||
| 8b6fe691ed | |||
| ccf9efdaa5 | |||
| bf66bec4c7 | |||
| 3319709526 | |||
| 7ceab5c88c | |||
| 94d4789e68 | |||
| b13985d550 | |||
| dc4a3e9b89 | |||
| d538c35532 | |||
| cfd26321b5 | |||
| 61d955f3de | |||
| a9f54c44e9 | |||
| 125877035f | |||
| 8f4b0c8078 | |||
| 1863e85bf5 | |||
| 488c6099fc | |||
| 67abc6d2cf | |||
| c56a57c0ba | |||
| 30b2c1ad61 | |||
| 5e279363e4 | |||
| abb7509f03 | |||
| 1cd60c05f3 | |||
| 510cc22484 | |||
| 3da664236c | |||
| 7e35a7fe0c | |||
| 58ef7db5d6 | |||
| f9de4a394c | |||
| dced5816df | |||
| 690ac740d2 | |||
| 89d0412e22 | |||
| a305752faf | |||
| 469b139e89 | |||
| 8f5d9c4816 | |||
| 7102c77e0b | |||
| 115ae21f1f | |||
| 8d3fdf45b9 | |||
| 1e7e5ea57c | |||
| 7c8b91456f | |||
| dc960f30f5 | |||
| ba12e31280 | |||
| 027a4081a2 | |||
| 190def17e5 | |||
| 9730526d33 | |||
| c87c843308 | |||
| 6453cdf0d6 | |||
| 5f80c33b24 | |||
| a33542c9b5 | |||
| 3a1d98648f | |||
| 4ec79d61d0 | |||
| b4f055f80c | |||
| 6bf35c679f | |||
| 3349d43c00 | |||
| ced961d24c | |||
| 419f708d87 | |||
| bbc1c04042 | |||
| 7a6865637d | |||
| ae96420925 | |||
| 2822812d0d | |||
| c8ab430491 | |||
| bb87f28e80 | |||
| 6db671215a | |||
| 64566ec6cf | |||
| faaf97ef62 | |||
| 67d6efed21 | |||
| 571d9bd610 | |||
| 4144698540 | |||
| 9bf6bf2c78 | |||
| cc9236b8db | |||
| 0103b59e61 | |||
| e9f6531db7 | |||
| 62c2c750ea | |||
| 3e5e3175e0 | |||
| 54c5af30d9 | |||
| ca4a3361c0 | |||
| 47d302221d | |||
| ed215657e6 | |||
| 3e63b14192 | |||
| 86433ab3a8 | |||
| 7214800d93 | |||
| 29f298fa4a | |||
| ef35bc77cb | |||
| 6ae880f61e | |||
| 0d1149310c | |||
| 51d32bb8d3 | |||
| 49a8980dea | |||
| 9fe1680c56 | |||
| b7db65a023 | |||
| 4c02002265 | |||
| d0198649f2 | |||
| 32c1fd082d | |||
| 363bf42b95 | |||
| a1ab2232f3 | |||
| cf69f43166 | |||
| 9833438733 | |||
| 67c5e3966a | |||
| aa0927911d | |||
| 13c9e1ed58 | |||
| 19a457ab7d | |||
| 0926bff0cc | |||
| 53a0bc963a | |||
| a2819d822a | |||
| 175112d97d | |||
| dced47024f | |||
| ffc361406e | |||
| 852c648235 | |||
| 1197b96c49 | |||
| f21fe81e16 | |||
| 593dfd0108 | |||
| aaf0fb9d12 | |||
| 02e9f8aef3 | |||
| 424055c04e | |||
| 02daf17326 | |||
| a666f0d52e | |||
| 27a760c58c | |||
| 0ba12f48c6 | |||
| eaaf54d886 | |||
| 4b3d634fe9 | |||
| f77a699ea4 | |||
| e989e38cc2 | |||
| 6a900ed6e7 | |||
| 29e6b85f79 | |||
| 2641408d53 | |||
| 5b79226183 | |||
| 98f9f0cd48 | |||
| cf7e107ad1 | |||
| ab66c1aa1b | |||
| 5b03366909 | |||
| 7824e1446a | |||
| 59cf1a4937 | |||
| 252113c838 | |||
| e2f84d1acd | |||
| 204dcecb28 | |||
| 70bbfbea12 | |||
| 2221a0a908 | |||
| 203b215093 | |||
| 76ee84dae8 | |||
| 79e1c87a01 | |||
| ed208114be | |||
| 7dd711b37c | |||
| 4852802d66 | |||
| c495b1faab | |||
| eb5bd8e6ac | |||
| ff7dcf9c17 | |||
| 2b12a16c84 | |||
| 4d00b2ebbb | |||
| 1ba5abbaef | |||
| b87a98bbda | |||
| f76361a345 | |||
| f25bab9555 | |||
| ed78b8429f | |||
| 94e9dd8f28 | |||
| 90215ca0dd | |||
| 34eb647fcb | |||
| 83205290de | |||
| 02fd528c32 | |||
| e05193f46d | |||
| 14e2d900b5 | |||
| ba4290340d | |||
| 5a04700bae | |||
| 999f50dce9 | |||
| 9522e6e714 | |||
| 7836ea4479 | |||
| 37e8ab8de1 | |||
| 34048497e7 | |||
| 5197422482 | |||
| d9987c2734 | |||
| c9671b4712 | |||
| bbf03e3060 | |||
| e35a78e3cf | |||
| e318be6a88 | |||
| 1dab0ebc25 | |||
| 687e58e9d4 | |||
| 993a4aa675 | |||
| c991510b0f | |||
| c8025bf004 | |||
| 9f5767a80c | |||
| ffb05d6271 | |||
| 2dd2d3dd7b | |||
| be29c7fca0 | |||
| 2c23a3c0b3 | |||
| 37e3ead8e9 | |||
| b018ea7b1b | |||
| d6cdca35d4 | |||
| a09d150b47 | |||
| 7cf46afc48 | |||
| 056c95670f | |||
| 35dffe43d9 | |||
| 19c26f0733 | |||
| 388ff10ff5 | |||
| 8c7be8e45f | |||
| 579aa67cde | |||
| 725f86a0d2 | |||
| 50a6ef18d2 | |||
| 1b3e924450 | |||
| a33e08e299 | |||
| 45dee5a666 | |||
| 642473244e | |||
| e92f344335 | |||
| 7951795ea4 | |||
| 101fbcca90 | |||
| d562132a4a | |||
| 7152ab39ff | |||
| 39c5279f5d | |||
| fef0e16f9c | |||
| fb1361b00d | |||
| 64c75c8b57 | |||
| f4e015a255 | |||
| 242b68c488 | |||
| 9452c7e0c7 | |||
| ab1d3d1ced | |||
| 41df92bb93 | |||
| 427db3f29a | |||
| b5600bdd7f | |||
| a2153b668a | |||
| 7d52c82c3b | |||
| 092f1a4959 | |||
| 21bee7e40c | |||
| a9ac0ac725 | |||
| 5dc1ed6696 | |||
| b55f66e69c | |||
| ab637e22b1 | |||
| fa665c5494 | |||
| e91b75a1bb | |||
| 4c6f85fd25 | |||
| f09e9b7790 | |||
| b51d3da7e5 | |||
| 861dbd5977 | |||
| 5001fcdd53 | |||
| eeb47dc724 | |||
| 5556dff11e | |||
| 18b57fa6aa | |||
| 12bb4d75fd | |||
| 411d8d4d98 | |||
| 748df0b21a | |||
| 8d98316a89 | |||
| c6b45a8e09 | |||
| d42920674a | |||
| c66fced161 | |||
| dee7c339b3 | |||
| 352bf8839b | |||
| 18f438a528 | |||
| 076944da5d | |||
| acbba95032 | |||
| 75f77783ff | |||
| 87e0f074e8 | |||
| 2211c69455 | |||
| a7449c913c | |||
| aaec0e641b | |||
| 5afed2d396 | |||
| 843348338a | |||
| 0f58ff8356 | |||
| 940b740b24 | |||
| 0f258f94a8 | |||
| fd7b22f639 | |||
| ca3464512d | |||
| f59cb6417f | |||
| 74ccb53607 | |||
| e4c6e98099 | |||
| cfab0fa245 | |||
| 08d861e87c | |||
| 73234e7782 | |||
| de8d28ea5f | |||
| ed7b478ee0 | |||
| ff9a216990 | |||
| 58c94159b1 | |||
| 7a1bd4d53a | |||
| 5d7c23c62a | |||
| d91d911051 | |||
| cd0cab465d | |||
| a45b887c5b | |||
| f965b7129b | |||
| e894ce00c9 | |||
| 333aba8be6 | |||
| e9d93ae210 | |||
| 043c8be747 | |||
| 1be67518df | |||
| 4bf1987bb7 | |||
| ae45eed2b1 | |||
| 572a9393aa | |||
| 7579c41a35 | |||
| 4e589c2575 | |||
| 026da34ce9 | |||
| 0daf49a1da | |||
| f57e4c6c14 | |||
| 14bd1d01f2 | |||
| 918e20b164 | |||
| 6a0e90ef90 | |||
| 71fe8ed80d | |||
| 581c9c570b | |||
| b25fe3d127 | |||
| fc4aef6d89 | |||
| 6b4fa6a40d | |||
| 6756eea209 | |||
| bf3cd37b49 | |||
| cc7caa9e16 | |||
| 633060562f | |||
| cc48546f62 | |||
| f2d9e4b2df | |||
| 049c7ad1f0 | |||
| 226dad651b | |||
| 0977cabc79 | |||
| 0b5e8a086e | |||
| e024ea5ee1 | |||
| 6f71092aa4 | |||
| edce44df97 | |||
| 54551d9f37 | |||
| 8521b5501f | |||
| 396dc21903 | |||
| 5e2b0ba46c | |||
| cce5d775de | |||
| 248a239c7b | |||
| 83655e9aef | |||
| 973d115edf | |||
| aaa9f89550 | |||
| 8afad5614a | |||
| a9fdabf926 | |||
| b5b262c722 | |||
| d1e1190cbd | |||
| 9812eaaca7 | |||
| 4520e04d37 | |||
| 5679b5862f | |||
| e72dc38d77 | |||
| 71fcfa4935 | |||
| c4463036c3 | |||
| b343a17b29 | |||
| 0b0fb249bf | |||
| 8d689974a7 | |||
| 375c81d38d | |||
| 0ef4f36d44 | |||
| c85f6c1228 | |||
| 0cabc81693 | |||
| 12b4fff81e | |||
| 27b6627110 | |||
| 387014dd37 | |||
| d5c91b9bda | |||
| 370f4f6257 | |||
| 49a665488e | |||
| 29da133726 | |||
| 1194bb8ae3 | |||
| 7599124aa0 | |||
| 01d2d91ecc | |||
| 6980d19214 | |||
| ac14a7b0da | |||
| 23f00ab533 | |||
| 39122bd61d | |||
| c5824765f9 | |||
| 547e942c66 | |||
| 2ab04e7e2f | |||
| a08fef172e | |||
| a04f77e7e0 | |||
| 4900f3e54d | |||
| 34ee6411d5 | |||
| 5abe7bc7e5 | |||
| a48aef4039 | |||
| cc94ab6411 | |||
| e67541e82f | |||
| d907be264b | |||
| 003c1df53e | |||
| f844e9e702 | |||
| 8753dbdb0f | |||
| 1bd24f7042 | |||
| 66d58bf047 | |||
| 1e5c4b0d79 | |||
| 711d402f17 | |||
| e19f54a378 | |||
| da277d9816 | |||
| 22dabc5180 | |||
| 91a2e56215 | |||
| e6681af9d0 |
@@ -72,7 +72,10 @@ stxxl.errlog
|
|||||||
/win/bin/
|
/win/bin/
|
||||||
/win/bin-debug/
|
/win/bin-debug/
|
||||||
/osrm-extract
|
/osrm-extract
|
||||||
|
/osrm-io-benchmark
|
||||||
|
/osrm-components
|
||||||
/osrm-routed
|
/osrm-routed
|
||||||
|
/osrm-datastore
|
||||||
/osrm-prepare
|
/osrm-prepare
|
||||||
/osrm-cli
|
/osrm-cli
|
||||||
/nohup.out
|
/nohup.out
|
||||||
|
|||||||
+2
-3
@@ -2,6 +2,7 @@ language: cpp
|
|||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
# - clang
|
# - clang
|
||||||
|
# Make sure CMake is installed
|
||||||
install:
|
install:
|
||||||
- sudo apt-get update >/dev/null
|
- sudo apt-get update >/dev/null
|
||||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
|
- sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
|
||||||
@@ -12,9 +13,6 @@ before_script:
|
|||||||
- cd build
|
- cd build
|
||||||
- cmake .. $CMAKEOPTIONS
|
- cmake .. $CMAKEOPTIONS
|
||||||
script: make
|
script: make
|
||||||
after_script:
|
|
||||||
- cd ..
|
|
||||||
- cucumber -p verify
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
@@ -30,6 +28,7 @@ notifications:
|
|||||||
on_failure: always
|
on_failure: always
|
||||||
use_notice: true
|
use_notice: true
|
||||||
skip_join: false
|
skip_join: false
|
||||||
|
|
||||||
recipients:
|
recipients:
|
||||||
- dennis@mapbox.com
|
- dennis@mapbox.com
|
||||||
email:
|
email:
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CRC32.h"
|
|
||||||
|
|
||||||
CRC32::CRC32() : crc(0) {
|
|
||||||
crcFunction = detectBestCRC32C();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::SoftwareBasedCRC32(char *str, unsigned len, unsigned ) {
|
|
||||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
|
|
||||||
CRC32_Processor.process_bytes( str, len);
|
|
||||||
return CRC32_Processor.checksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::SSEBasedCRC32( char *str, unsigned len, unsigned crc) {
|
|
||||||
unsigned q=len/sizeof(unsigned),
|
|
||||||
r=len%sizeof(unsigned),
|
|
||||||
*p=(unsigned*)str/*, crc*/;
|
|
||||||
|
|
||||||
//crc=0;
|
|
||||||
while (q--) {
|
|
||||||
__asm__ __volatile__(
|
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
|
||||||
:"=S"(crc)
|
|
||||||
:"0"(crc), "c"(*p)
|
|
||||||
);
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
|
|
||||||
str=(char*)p;
|
|
||||||
while (r--) {
|
|
||||||
__asm__ __volatile__(
|
|
||||||
".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
|
|
||||||
:"=S"(crc)
|
|
||||||
:"0"(crc), "c"(*str)
|
|
||||||
);
|
|
||||||
++str;
|
|
||||||
}
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
|
|
||||||
static const int SSE42_BIT = 20;
|
|
||||||
unsigned ecx = cpuid(1);
|
|
||||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
|
||||||
if (hasSSE42) {
|
|
||||||
SimpleLogger().Write() << "using hardware base sse computation";
|
|
||||||
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
|
||||||
} else {
|
|
||||||
SimpleLogger().Write() << "using software base sse computation";
|
|
||||||
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::cpuid(unsigned functionInput) {
|
|
||||||
unsigned eax;
|
|
||||||
unsigned ebx;
|
|
||||||
unsigned ecx;
|
|
||||||
unsigned edx;
|
|
||||||
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
|
|
||||||
return ecx;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned CRC32::operator()(char *str, unsigned len){
|
|
||||||
crc =((*this).*(crcFunction))(str, len, crc);
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
+7
-108
@@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define DOUGLASPEUCKER_H_
|
#define DOUGLASPEUCKER_H_
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@@ -45,11 +46,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
* indicating if the points is present in the generalization.
|
* indicating if the points is present in the generalization.
|
||||||
* Note: points may also be pre-selected*/
|
* Note: points may also be pre-selected*/
|
||||||
|
|
||||||
//These thresholds are more or less heuristically chosen.
|
|
||||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
|
||||||
static double DouglasPeuckerThresholds[19] = { 32000000., 16240000., 80240000., 40240000., 20000000., 10000000., 500000., 240000., 120000., 60000., 30000., 19000., 5000., 2000., 200, 16, 6, 3. , 3. };
|
|
||||||
|
|
||||||
template<class PointT>
|
|
||||||
class DouglasPeucker {
|
class DouglasPeucker {
|
||||||
private:
|
private:
|
||||||
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
||||||
@@ -60,111 +56,14 @@ private:
|
|||||||
* This distance computation does integer arithmetic only and is about twice as fast as
|
* This distance computation does integer arithmetic only and is about twice as fast as
|
||||||
* the other distance function. It is an approximation only, but works more or less ok.
|
* the other distance function. It is an approximation only, but works more or less ok.
|
||||||
*/
|
*/
|
||||||
template<class CoordT>
|
int fastDistance(
|
||||||
inline int fastDistance(const CoordT& point, const CoordT& segA, const CoordT& segB) const {
|
const FixedPointCoordinate& point,
|
||||||
const int p2x = (segB.lon - segA.lat);
|
const FixedPointCoordinate& segA,
|
||||||
const int p2y = (segB.lon - segA.lat);
|
const FixedPointCoordinate& segB
|
||||||
const int something = p2x*p2x + p2y*p2y;
|
) const;
|
||||||
int u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
|
|
||||||
|
|
||||||
if (u > 1) {
|
|
||||||
u = 1;
|
|
||||||
} else if (u < 0) {
|
|
||||||
u = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int x = segA.lon + u * p2x;
|
|
||||||
const int y = segA.lat + u * p2y;
|
|
||||||
|
|
||||||
const int dx = x - point.lon;
|
|
||||||
const int dy = y - point.lat;
|
|
||||||
|
|
||||||
const int dist = (dx*dx + dy*dy);
|
|
||||||
|
|
||||||
return dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Run(std::vector<PointT> & input_geometry, const unsigned zoom_level) {
|
void Run(std::vector<SegmentInformation> & input_geometry, const unsigned zoom_level);
|
||||||
{
|
|
||||||
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
|
||||||
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
|
||||||
std::size_t left_border = 0;
|
|
||||||
std::size_t right_border = 1;
|
|
||||||
//Sweep linerarily over array and identify those ranges that need to be checked
|
|
||||||
do {
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
input_geometry[left_border].necessary,
|
|
||||||
"left border must be necessary"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
input_geometry.back().necessary,
|
|
||||||
"right border must be necessary"
|
|
||||||
);
|
|
||||||
|
|
||||||
if(input_geometry[right_border].necessary) {
|
|
||||||
recursion_stack.push(std::make_pair(left_border, right_border));
|
|
||||||
left_border = right_border;
|
|
||||||
}
|
|
||||||
++right_border;
|
|
||||||
} while( right_border < input_geometry.size());
|
|
||||||
}
|
|
||||||
while(!recursion_stack.empty()) {
|
|
||||||
//pop next element
|
|
||||||
const PairOfPoints pair = recursion_stack.top();
|
|
||||||
recursion_stack.pop();
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
input_geometry[pair.first].necessary,
|
|
||||||
"left border mus be necessary"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
input_geometry[pair.second].necessary,
|
|
||||||
"right border must be necessary"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
pair.second < input_geometry.size(),
|
|
||||||
"right border outside of geometry"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
pair.first < pair.second,
|
|
||||||
"left border on the wrong side"
|
|
||||||
);
|
|
||||||
int max_distance = INT_MIN;
|
|
||||||
|
|
||||||
std::size_t farthest_element_index = pair.second;
|
|
||||||
//find index idx of element with max_distance
|
|
||||||
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
|
||||||
const int temp_dist = fastDistance(
|
|
||||||
input_geometry[i].location,
|
|
||||||
input_geometry[pair.first].location,
|
|
||||||
input_geometry[pair.second].location
|
|
||||||
);
|
|
||||||
const double distance = std::fabs(temp_dist);
|
|
||||||
if(
|
|
||||||
distance > DouglasPeuckerThresholds[zoom_level] &&
|
|
||||||
distance > max_distance
|
|
||||||
) {
|
|
||||||
farthest_element_index = i;
|
|
||||||
max_distance = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
|
|
||||||
// mark idx as necessary
|
|
||||||
input_geometry[farthest_element_index].necessary = true;
|
|
||||||
if (1 < (farthest_element_index - pair.first) ) {
|
|
||||||
recursion_stack.push(
|
|
||||||
std::make_pair(pair.first, farthest_element_index)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (1 < (pair.second - farthest_element_index) ) {
|
|
||||||
recursion_stack.push(
|
|
||||||
std::make_pair(farthest_element_index, pair.second)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DOUGLASPEUCKER_H_ */
|
#endif /* DOUGLASPEUCKER_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DouglasPeucker.h"
|
||||||
|
|
||||||
|
//These thresholds are more or less heuristically chosen.
|
||||||
|
static double DouglasPeuckerThresholds[19] = {
|
||||||
|
32000000., //z0
|
||||||
|
16240000., //z1
|
||||||
|
8240000., //z2
|
||||||
|
4240000., //z3
|
||||||
|
2000000., //z4
|
||||||
|
1000000., //z5
|
||||||
|
500000., //z6
|
||||||
|
240000., //z7
|
||||||
|
120000., //z8
|
||||||
|
60000., //z9
|
||||||
|
30000., //z10
|
||||||
|
19000., //z11
|
||||||
|
5000., //z12
|
||||||
|
2000., //z13
|
||||||
|
200., //z14
|
||||||
|
16., //z15
|
||||||
|
6., //z16
|
||||||
|
3., //z17
|
||||||
|
3. //z18
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This distance computation does integer arithmetic only and is about twice as
|
||||||
|
* fast as the other distance function. It is an approximation only, but works
|
||||||
|
* more or less ok.
|
||||||
|
*/
|
||||||
|
int DouglasPeucker::fastDistance(
|
||||||
|
const FixedPointCoordinate& point,
|
||||||
|
const FixedPointCoordinate& segA,
|
||||||
|
const FixedPointCoordinate& segB
|
||||||
|
) const {
|
||||||
|
const int p2x = (segB.lon - segA.lon);
|
||||||
|
const int p2y = (segB.lat - segA.lat);
|
||||||
|
const int something = p2x*p2x + p2y*p2y;
|
||||||
|
double u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
|
||||||
|
|
||||||
|
if (u > 1) {
|
||||||
|
u = 1;
|
||||||
|
} else if (u < 0) {
|
||||||
|
u = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int x = segA.lon + u * p2x;
|
||||||
|
const int y = segA.lat + u * p2y;
|
||||||
|
|
||||||
|
const int dx = x - point.lon;
|
||||||
|
const int dy = y - point.lat;
|
||||||
|
|
||||||
|
const int dist = (dx*dx + dy*dy);
|
||||||
|
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DouglasPeucker::Run(
|
||||||
|
std::vector<SegmentInformation> & input_geometry,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) {
|
||||||
|
{
|
||||||
|
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||||
|
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
||||||
|
std::size_t left_border = 0;
|
||||||
|
std::size_t right_border = 1;
|
||||||
|
//Sweep linerarily over array and identify those ranges that need to be checked
|
||||||
|
do {
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry[left_border].necessary,
|
||||||
|
"left border must be necessary"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry.back().necessary,
|
||||||
|
"right border must be necessary"
|
||||||
|
);
|
||||||
|
|
||||||
|
if(input_geometry[right_border].necessary) {
|
||||||
|
recursion_stack.push(std::make_pair(left_border, right_border));
|
||||||
|
left_border = right_border;
|
||||||
|
}
|
||||||
|
++right_border;
|
||||||
|
} while( right_border < input_geometry.size());
|
||||||
|
}
|
||||||
|
while(!recursion_stack.empty()) {
|
||||||
|
//pop next element
|
||||||
|
const PairOfPoints pair = recursion_stack.top();
|
||||||
|
recursion_stack.pop();
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry[pair.first].necessary,
|
||||||
|
"left border mus be necessary"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
input_geometry[pair.second].necessary,
|
||||||
|
"right border must be necessary"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
pair.second < input_geometry.size(),
|
||||||
|
"right border outside of geometry"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
pair.first < pair.second,
|
||||||
|
"left border on the wrong side"
|
||||||
|
);
|
||||||
|
int max_distance = INT_MIN;
|
||||||
|
|
||||||
|
std::size_t farthest_element_index = pair.second;
|
||||||
|
//find index idx of element with max_distance
|
||||||
|
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
||||||
|
const int temp_dist = fastDistance(
|
||||||
|
input_geometry[i].location,
|
||||||
|
input_geometry[pair.first].location,
|
||||||
|
input_geometry[pair.second].location
|
||||||
|
);
|
||||||
|
const double distance = std::fabs(temp_dist);
|
||||||
|
if(
|
||||||
|
distance > DouglasPeuckerThresholds[zoom_level] &&
|
||||||
|
distance > max_distance
|
||||||
|
) {
|
||||||
|
farthest_element_index = i;
|
||||||
|
max_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (max_distance > DouglasPeuckerThresholds[zoom_level]) {
|
||||||
|
// mark idx as necessary
|
||||||
|
input_geometry[farthest_element_index].necessary = true;
|
||||||
|
if (1 < (farthest_element_index - pair.first) ) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(pair.first, farthest_element_index)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (1 < (pair.second - farthest_element_index) ) {
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(farthest_element_index, pair.second)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PolylineCompressor.h"
|
||||||
|
|
||||||
|
void PolylineCompressor::encodeVectorSignedNumber(
|
||||||
|
std::vector<int> & numbers,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||||
|
numbers[i] <<= 1;
|
||||||
|
if (numbers[i] < 0) {
|
||||||
|
numbers[i] = ~(numbers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(unsigned i = 0; i < numbers.size(); ++i) {
|
||||||
|
encodeNumber(numbers[i], output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::encodeNumber(int number_to_encode, std::string & output) const {
|
||||||
|
while (number_to_encode >= 0x20) {
|
||||||
|
int nextValue = (0x20 | (number_to_encode & 0x1f)) + 63;
|
||||||
|
output += static_cast<char>(nextValue);
|
||||||
|
if(92 == nextValue) {
|
||||||
|
output += static_cast<char>(nextValue);
|
||||||
|
}
|
||||||
|
number_to_encode >>= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
number_to_encode += 63;
|
||||||
|
output += static_cast<char>(number_to_encode);
|
||||||
|
if(92 == number_to_encode) {
|
||||||
|
output += static_cast<char>(number_to_encode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printEncodedString(
|
||||||
|
const std::vector<SegmentInformation> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
std::vector<int> deltaNumbers;
|
||||||
|
output += "\"";
|
||||||
|
if(!polyline.empty()) {
|
||||||
|
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
||||||
|
deltaNumbers.push_back( lastCoordinate.lat );
|
||||||
|
deltaNumbers.push_back( lastCoordinate.lon );
|
||||||
|
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||||
|
if(!polyline[i].necessary) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
||||||
|
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
||||||
|
lastCoordinate = polyline[i].location;
|
||||||
|
}
|
||||||
|
encodeVectorSignedNumber(deltaNumbers, output);
|
||||||
|
}
|
||||||
|
output += "\"";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printEncodedString(
|
||||||
|
const std::vector<FixedPointCoordinate>& polyline,
|
||||||
|
std::string &output
|
||||||
|
) const {
|
||||||
|
std::vector<int> deltaNumbers(2*polyline.size());
|
||||||
|
output += "\"";
|
||||||
|
if(!polyline.empty()) {
|
||||||
|
deltaNumbers[0] = polyline[0].lat;
|
||||||
|
deltaNumbers[1] = polyline[0].lon;
|
||||||
|
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||||
|
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
||||||
|
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
||||||
|
}
|
||||||
|
encodeVectorSignedNumber(deltaNumbers, output);
|
||||||
|
}
|
||||||
|
output += "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printUnencodedString(
|
||||||
|
const std::vector<FixedPointCoordinate> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
output += "[";
|
||||||
|
std::string tmp;
|
||||||
|
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||||
|
convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||||
|
output += "[";
|
||||||
|
output += tmp;
|
||||||
|
convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||||
|
output += ", ";
|
||||||
|
output += tmp;
|
||||||
|
output += "]";
|
||||||
|
if( i < polyline.size()-1 ) {
|
||||||
|
output += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolylineCompressor::printUnencodedString(
|
||||||
|
const std::vector<SegmentInformation> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
|
output += "[";
|
||||||
|
std::string tmp;
|
||||||
|
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||||
|
if(!polyline[i].necessary) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||||
|
output += "[";
|
||||||
|
output += tmp;
|
||||||
|
convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||||
|
output += ", ";
|
||||||
|
output += tmp;
|
||||||
|
output += "]";
|
||||||
|
if( i < polyline.size()-1 ) {
|
||||||
|
output += ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += "]";
|
||||||
|
}
|
||||||
@@ -32,112 +32,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class PolylineCompressor {
|
class PolylineCompressor {
|
||||||
private:
|
private:
|
||||||
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
|
void encodeVectorSignedNumber(
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
std::vector<int> & numbers,
|
||||||
numbers[i] <<= 1;
|
std::string & output
|
||||||
if (numbers[i] < 0) {
|
) const;
|
||||||
numbers[i] = ~(numbers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(unsigned i = 0; i < numbers.size(); ++i) {
|
|
||||||
encodeNumber(numbers[i], output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void encodeNumber(int numberToEncode, std::string & output) const {
|
void encodeNumber(int number_to_encode, std::string & output) const;
|
||||||
while (numberToEncode >= 0x20) {
|
|
||||||
int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
|
|
||||||
output += (static_cast<char> (nextValue));
|
|
||||||
if(92 == nextValue)
|
|
||||||
output += (static_cast<char> (nextValue));
|
|
||||||
numberToEncode >>= 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
numberToEncode += 63;
|
|
||||||
output += (static_cast<char> (numberToEncode));
|
|
||||||
if(92 == numberToEncode)
|
|
||||||
output += (static_cast<char> (numberToEncode));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void printEncodedString(
|
void printEncodedString(
|
||||||
const std::vector<SegmentInformation> & polyline,
|
const std::vector<SegmentInformation> & polyline,
|
||||||
std::string & output
|
std::string & output
|
||||||
) const {
|
) const;
|
||||||
std::vector<int> deltaNumbers;
|
|
||||||
output += "\"";
|
|
||||||
if(!polyline.empty()) {
|
|
||||||
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
|
||||||
deltaNumbers.push_back( lastCoordinate.lat );
|
|
||||||
deltaNumbers.push_back( lastCoordinate.lon );
|
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
|
||||||
if(!polyline[i].necessary)
|
|
||||||
continue;
|
|
||||||
deltaNumbers.push_back(polyline[i].location.lat - lastCoordinate.lat);
|
|
||||||
deltaNumbers.push_back(polyline[i].location.lon - lastCoordinate.lon);
|
|
||||||
lastCoordinate = polyline[i].location;
|
|
||||||
}
|
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
|
||||||
}
|
|
||||||
output += "\"";
|
|
||||||
|
|
||||||
}
|
void printEncodedString(
|
||||||
|
const std::vector<FixedPointCoordinate>& polyline,
|
||||||
|
std::string &output
|
||||||
|
) const;
|
||||||
|
|
||||||
inline void printEncodedString(const std::vector<FixedPointCoordinate>& polyline, std::string &output) const {
|
void printUnencodedString(
|
||||||
std::vector<int> deltaNumbers(2*polyline.size());
|
const std::vector<FixedPointCoordinate> & polyline,
|
||||||
output += "\"";
|
std::string & output
|
||||||
if(!polyline.empty()) {
|
) const;
|
||||||
deltaNumbers[0] = polyline[0].lat;
|
|
||||||
deltaNumbers[1] = polyline[0].lon;
|
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
|
||||||
deltaNumbers[(2*i)] = (polyline[i].lat - polyline[i-1].lat);
|
|
||||||
deltaNumbers[(2*i)+1] = (polyline[i].lon - polyline[i-1].lon);
|
|
||||||
}
|
|
||||||
encodeVectorSignedNumber(deltaNumbers, output);
|
|
||||||
}
|
|
||||||
output += "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printUnencodedString(std::vector<FixedPointCoordinate> & polyline, std::string & output) const {
|
void printUnencodedString(
|
||||||
output += "[";
|
const std::vector<SegmentInformation> & polyline,
|
||||||
std::string tmp;
|
std::string & output
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
) const;
|
||||||
convertInternalLatLonToString(polyline[i].lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
|
||||||
convertInternalLatLonToString(polyline[i].lon, tmp);
|
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output += "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void printUnencodedString(std::vector<SegmentInformation> & polyline, std::string & output) const {
|
|
||||||
output += "[";
|
|
||||||
std::string tmp;
|
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
|
||||||
if(!polyline[i].necessary)
|
|
||||||
continue;
|
|
||||||
convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
|
||||||
output += "[";
|
|
||||||
output += tmp;
|
|
||||||
convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
|
||||||
output += ", ";
|
|
||||||
output += tmp;
|
|
||||||
output += "]";
|
|
||||||
if( i < polyline.size()-1 ) {
|
|
||||||
output += ",";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output += "]";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||||
|
|||||||
+75
-36
@@ -1,8 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
||||||
project(OSRM)
|
project(OSRM)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
set(HUGO "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
@@ -30,29 +29,34 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
|||||||
|
|
||||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
||||||
|
|
||||||
set(BOOST_COMPONENTS filesystem program_options regex system thread)
|
set(BOOST_COMPONENTS filesystem iostreams program_options regex system thread)
|
||||||
|
|
||||||
configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp)
|
configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp)
|
||||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
set(ExtractorSources extractor.cpp ${ExtractorGlob} Util/GitDescription.cpp)
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
add_executable(osrm-extract ${ExtractorSources} )
|
add_executable(osrm-extract ${ExtractorSources} )
|
||||||
|
|
||||||
file(GLOB PrepareGlob Contractor/*.cpp)
|
file( GLOB PrepareGlob Contractor/*.cpp )
|
||||||
set(PrepareSources createHierarchy.cpp ${PrepareGlob} Util/GitDescription.cpp)
|
set( PrepareSources prepare.cpp ${PrepareGlob} )
|
||||||
add_executable(osrm-prepare ${PrepareSources} )
|
add_executable( osrm-prepare ${PrepareSources} )
|
||||||
|
|
||||||
add_executable(osrm-routed routed.cpp Util/GitDescription.cpp)
|
|
||||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
|
||||||
|
|
||||||
|
file(GLOB ServerGlob Server/*.cpp)
|
||||||
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||||
|
file(GLOB DatastructureGlob DataStructures/*.cpp)
|
||||||
|
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
||||||
|
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||||
file(GLOB SearchEngineSource DataStructures/SearchEngine*.cpp)
|
|
||||||
file(GLOB ServerStructureGlob Server/DataStructures/*.cpp)
|
|
||||||
|
|
||||||
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${SearchEngineSource} ${ServerStructureGlob})
|
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob} ${AlgorithmGlob} ${HttpGlob})
|
||||||
add_library(OSRM SHARED ${OSRMSources})
|
add_library( OSRM SHARED ${OSRMSources} )
|
||||||
add_library(UUID STATIC Util/UUID.cpp)
|
add_library( UUID STATIC Util/UUID.cpp )
|
||||||
|
add_library( GITDESCRIPTION STATIC Util/GitDescription.cpp )
|
||||||
add_dependencies( UUID UUIDConfigure )
|
add_dependencies( UUID UUIDConfigure )
|
||||||
|
add_dependencies( GITDESCRIPTION GIT_DESCRIPTION )
|
||||||
|
|
||||||
|
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
||||||
|
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||||
|
add_executable(osrm-datastore datastore.cpp)
|
||||||
|
|
||||||
# Check the release mode
|
# Check the release mode
|
||||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
@@ -65,7 +69,14 @@ if(CMAKE_BUILD_TYPE MATCHES Release)
|
|||||||
message(STATUS "Configuring OSRM in release mode")
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
|
||||||
#Configuring compilers
|
# set compile switches
|
||||||
|
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
# not using Visual Studio C++
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Configuring compilers
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
# using Clang
|
# using Clang
|
||||||
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
||||||
@@ -80,11 +91,23 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
|||||||
# using Visual Studio C++
|
# using Visual Studio C++
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Configuring other platform dependencies
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||||
message("Set Architecture to x64 on OS X")
|
message(STATUS "Set Architecture to x64 on OS X")
|
||||||
|
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||||
|
STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||||
|
IF (DARWIN_VERSION GREATER 12)
|
||||||
|
MESSAGE(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||||
|
ENDIF (DARWIN_VERSION GREATER 12)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries( osrm-datastore rt )
|
||||||
|
target_link_libraries( OSRM rt )
|
||||||
|
endif(UNIX AND NOT APPLE)
|
||||||
|
|
||||||
#Check Boost
|
#Check Boost
|
||||||
set(BOOST_MIN_VERSION "1.44.0")
|
set(BOOST_MIN_VERSION "1.44.0")
|
||||||
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
||||||
@@ -98,9 +121,10 @@ IF( APPLE )
|
|||||||
ELSE( APPLE )
|
ELSE( APPLE )
|
||||||
target_link_libraries( OSRM ${Boost_LIBRARIES} )
|
target_link_libraries( OSRM ${Boost_LIBRARIES} )
|
||||||
ENDIF( APPLE )
|
ENDIF( APPLE )
|
||||||
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID )
|
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||||
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID )
|
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||||
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID )
|
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
||||||
|
target_link_libraries( osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||||
|
|
||||||
find_package ( BZip2 REQUIRED )
|
find_package ( BZip2 REQUIRED )
|
||||||
include_directories(${BZIP_INCLUDE_DIRS})
|
include_directories(${BZIP_INCLUDE_DIRS})
|
||||||
@@ -114,17 +138,27 @@ target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
|||||||
find_package( Threads REQUIRED )
|
find_package( Threads REQUIRED )
|
||||||
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
||||||
|
|
||||||
find_package( LuaJIT )
|
find_package( Lua52 )
|
||||||
IF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES)
|
IF ( NOT LUA52_FOUND )
|
||||||
include_directories(${LUAJIT_INCLUDE_DIR})
|
find_package( Lua51 REQUIRED )
|
||||||
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
|
IF (NOT APPLE)
|
||||||
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
|
find_package( LuaJIT 5.1 )
|
||||||
ELSE( LUAJIT_INCLUDE_DIR )
|
ENDIF ( NOT APPLE )
|
||||||
find_package( Lua51 REQUIRED AND LUAJIT_LIBRARIES )
|
ELSE( NOT LUA52_FOUND )
|
||||||
include_directories(${LUA_INCLUDE_DIR})
|
IF(NOT APPLE)
|
||||||
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
find_package( LuaJIT 5.2 )
|
||||||
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
ENDIF(NOT APPLE)
|
||||||
ENDIF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES )
|
ENDIF( NOT LUA52_FOUND )
|
||||||
|
|
||||||
|
IF ( LUAJIT_FOUND )
|
||||||
|
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
|
||||||
|
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
|
||||||
|
ELSE ()
|
||||||
|
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
||||||
|
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
||||||
|
ENDIF ()
|
||||||
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
|
|
||||||
|
|
||||||
find_package( LibXml2 REQUIRED )
|
find_package( LibXml2 REQUIRED )
|
||||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
@@ -152,17 +186,22 @@ target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
|
|||||||
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
||||||
|
|
||||||
if(WITH_TOOLS)
|
if(WITH_TOOLS)
|
||||||
message("-- Activating OSRM internal tools")
|
message(STATUS "Activating OSRM internal tools")
|
||||||
find_package( GDAL )
|
find_package( GDAL )
|
||||||
if(GDAL_FOUND)
|
if(GDAL_FOUND)
|
||||||
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
||||||
include_directories(${GDAL_INCLUDE_DIR})
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID
|
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION
|
||||||
)
|
)
|
||||||
endif(GDAL_FOUND)
|
endif(GDAL_FOUND)
|
||||||
add_executable ( osrm-cli Tools/simpleclient.cpp Util/GitDescription.cpp)
|
add_executable ( osrm-cli Tools/simpleclient.cpp)
|
||||||
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID )
|
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
||||||
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} )
|
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||||
|
add_executable ( osrm-unlock-all Tools/unlock_all_mutexes.cpp )
|
||||||
|
target_link_libraries( osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||||
|
if(UNIX AND NOT APPLE)
|
||||||
|
target_link_libraries( osrm-unlock-all rt )
|
||||||
|
endif(UNIX AND NOT APPLE)
|
||||||
endif(WITH_TOOLS)
|
endif(WITH_TOOLS)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ 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/DynamicGraph.h"
|
||||||
|
#include "../DataStructures/EdgeBasedNode.h"
|
||||||
#include "../Extractor/ExtractorStructs.h"
|
#include "../Extractor/ExtractorStructs.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
@@ -56,51 +57,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
struct EdgeBasedNode {
|
|
||||||
EdgeBasedNode() :
|
|
||||||
id(INT_MAX),
|
|
||||||
lat1(INT_MAX),
|
|
||||||
lat2(INT_MAX),
|
|
||||||
lon1(INT_MAX),
|
|
||||||
lon2(INT_MAX >> 1),
|
|
||||||
belongsToTinyComponent(false),
|
|
||||||
nameID(UINT_MAX),
|
|
||||||
weight(UINT_MAX >> 1),
|
|
||||||
ignoreInGrid(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
|
||||||
return other.id < id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
|
||||||
return id == other.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedPointCoordinate Centroid() const {
|
|
||||||
FixedPointCoordinate centroid;
|
|
||||||
//The coordinates of the midpoint are given by:
|
|
||||||
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
|
||||||
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
|
||||||
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
|
||||||
return centroid;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isIgnored() const {
|
|
||||||
return ignoreInGrid;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID id;
|
|
||||||
int lat1;
|
|
||||||
int lat2;
|
|
||||||
int lon1;
|
|
||||||
int lon2:31;
|
|
||||||
bool belongsToTinyComponent:1;
|
|
||||||
NodeID nameID;
|
|
||||||
unsigned weight:31;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SpeedProfileProperties{
|
struct SpeedProfileProperties{
|
||||||
SpeedProfileProperties() :
|
SpeedProfileProperties() :
|
||||||
trafficSignalPenalty(0),
|
trafficSignalPenalty(0),
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -132,6 +132,10 @@ public:
|
|||||||
return static_cast<Key>( heap.size() - 1 );
|
return static_cast<Key>( heap.size() - 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Empty() const {
|
||||||
|
return 0 == Size();
|
||||||
|
}
|
||||||
|
|
||||||
void Insert( NodeID node, Weight weight, const Data &data ) {
|
void Insert( NodeID node, Weight weight, const Data &data ) {
|
||||||
HeapElement element;
|
HeapElement element;
|
||||||
element.index = static_cast<NodeID>(insertedNodes.size());
|
element.index = static_cast<NodeID>(insertedNodes.size());
|
||||||
@@ -155,7 +159,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WasRemoved( const NodeID node ) {
|
bool WasRemoved( const NodeID node ) {
|
||||||
assert( WasInserted( node ) );
|
BOOST_ASSERT( WasInserted( node ) );
|
||||||
const Key index = nodeIndex[node];
|
const Key index = nodeIndex[node];
|
||||||
return insertedNodes[index].key == 0;
|
return insertedNodes[index].key == 0;
|
||||||
}
|
}
|
||||||
@@ -168,12 +172,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
NodeID Min() const {
|
NodeID Min() const {
|
||||||
assert( heap.size() > 1 );
|
BOOST_ASSERT( heap.size() > 1 );
|
||||||
return insertedNodes[heap[1].index].node;
|
return insertedNodes[heap[1].index].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID DeleteMin() {
|
NodeID DeleteMin() {
|
||||||
assert( heap.size() > 1 );
|
BOOST_ASSERT( heap.size() > 1 );
|
||||||
const Key removedIndex = heap[1].index;
|
const Key removedIndex = heap[1].index;
|
||||||
heap[1] = heap[heap.size()-1];
|
heap[1] = heap[heap.size()-1];
|
||||||
heap.pop_back();
|
heap.pop_back();
|
||||||
@@ -192,10 +196,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DecreaseKey( NodeID node, Weight weight ) {
|
void DecreaseKey( NodeID node, Weight weight ) {
|
||||||
assert( UINT_MAX != node );
|
BOOST_ASSERT( UINT_MAX != node );
|
||||||
const Key & index = nodeIndex[node];
|
const Key & index = nodeIndex[node];
|
||||||
Key & key = insertedNodes[index].key;
|
Key & key = insertedNodes[index].key;
|
||||||
assert ( key >= 0 );
|
BOOST_ASSERT ( key >= 0 );
|
||||||
|
|
||||||
insertedNodes[index].weight = weight;
|
insertedNodes[index].weight = weight;
|
||||||
heap[key].weight = weight;
|
heap[key].weight = weight;
|
||||||
@@ -253,7 +257,7 @@ private:
|
|||||||
const Weight weight = heap[key].weight;
|
const Weight weight = heap[key].weight;
|
||||||
Key nextKey = key >> 1;
|
Key nextKey = key >> 1;
|
||||||
while ( heap[nextKey].weight > weight ) {
|
while ( heap[nextKey].weight > weight ) {
|
||||||
assert( nextKey != 0 );
|
BOOST_ASSERT( nextKey != 0 );
|
||||||
heap[key] = heap[nextKey];
|
heap[key] = heap[nextKey];
|
||||||
insertedNodes[heap[key].index].key = key;
|
insertedNodes[heap[key].index].key = key;
|
||||||
key = nextKey;
|
key = nextKey;
|
||||||
@@ -267,7 +271,7 @@ private:
|
|||||||
void CheckHeap() {
|
void CheckHeap() {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
for ( Key i = 2; i < (Key) heap.size(); ++i ) {
|
||||||
assert( heap[i].weight >= heap[i >> 1].weight );
|
BOOST_ASSERT( heap[i].weight >= heap[i >> 1].weight );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/MercatorUtil.h"
|
#include "../DataStructures/MercatorUtil.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <boost/assert.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
@@ -74,10 +74,10 @@ inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
|
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
|
||||||
assert(lat1 != INT_MIN);
|
BOOST_ASSERT(lat1 != INT_MIN);
|
||||||
assert(lon1 != INT_MIN);
|
BOOST_ASSERT(lon1 != INT_MIN);
|
||||||
assert(lat2 != INT_MIN);
|
BOOST_ASSERT(lat2 != INT_MIN);
|
||||||
assert(lon2 != INT_MIN);
|
BOOST_ASSERT(lon2 != INT_MIN);
|
||||||
double RAD = 0.017453292519943295769236907684886;
|
double RAD = 0.017453292519943295769236907684886;
|
||||||
double lt1 = lat1/COORDINATE_PRECISION;
|
double lt1 = lat1/COORDINATE_PRECISION;
|
||||||
double ln1 = lon1/COORDINATE_PRECISION;
|
double ln1 = lon1/COORDINATE_PRECISION;
|
||||||
@@ -106,10 +106,10 @@ inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPoi
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||||
assert(c1.lat != INT_MIN);
|
BOOST_ASSERT(c1.lat != INT_MIN);
|
||||||
assert(c1.lon != INT_MIN);
|
BOOST_ASSERT(c1.lon != INT_MIN);
|
||||||
assert(c2.lat != INT_MIN);
|
BOOST_ASSERT(c2.lat != INT_MIN);
|
||||||
assert(c2.lon != INT_MIN);
|
BOOST_ASSERT(c2.lon != INT_MIN);
|
||||||
const double RAD = 0.017453292519943295769236907684886;
|
const double RAD = 0.017453292519943295769236907684886;
|
||||||
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
||||||
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef DEALLOCATINGVECTOR_H_
|
#ifndef DEALLOCATINGVECTOR_H_
|
||||||
#define DEALLOCATINGVECTOR_H_
|
#define DEALLOCATINGVECTOR_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include <boost/assert.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -48,45 +48,32 @@ protected:
|
|||||||
//make constructors explicit, so we do not mix random access and deallocation iterators.
|
//make constructors explicit, so we do not mix random access and deallocation iterators.
|
||||||
DeallocatingVectorIteratorState();
|
DeallocatingVectorIteratorState();
|
||||||
public:
|
public:
|
||||||
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : mData(r.mData), mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
explicit DeallocatingVectorIteratorState(const DeallocatingVectorIteratorState &r) : /*mData(r.mData),*/ mIndex(r.mIndex), mBucketList(r.mBucketList) {}
|
||||||
//explicit DeallocatingVectorIteratorState(const ElementT * ptr, const std::size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
|
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : /*mData(DEALLOCATION_VECTOR_NULL_PTR),*/ mIndex(idx), mBucketList(input_list) {
|
||||||
explicit DeallocatingVectorIteratorState(const std::size_t idx, std::vector<ElementT *> & input_list) : mData(DEALLOCATION_VECTOR_NULL_PTR), mIndex(idx), mBucketList(input_list) {
|
|
||||||
setPointerForIndex();
|
|
||||||
}
|
}
|
||||||
ElementT * mData;
|
|
||||||
std::size_t mIndex;
|
std::size_t mIndex;
|
||||||
std::vector<ElementT *> & mBucketList;
|
std::vector<ElementT *> & mBucketList;
|
||||||
|
|
||||||
inline void setPointerForIndex() {
|
|
||||||
if(bucketSizeC*mBucketList.size() <= mIndex) {
|
|
||||||
mData = DEALLOCATION_VECTOR_NULL_PTR;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::size_t _bucket = mIndex/bucketSizeC;
|
|
||||||
std::size_t _index = mIndex%bucketSizeC;
|
|
||||||
mData = &(mBucketList[_bucket][_index]);
|
|
||||||
|
|
||||||
if(DeallocateC) {
|
|
||||||
//if we hopped over the border of the previous bucket, then delete that bucket.
|
|
||||||
if(0 == _index && _bucket) {
|
|
||||||
delete[] mBucketList[_bucket-1];
|
|
||||||
mBucketList[_bucket-1] = DEALLOCATION_VECTOR_NULL_PTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
inline bool operator!=(const DeallocatingVectorIteratorState &other) {
|
||||||
return (mData != other.mData) || (mIndex != other.mIndex) || (mBucketList != other.mBucketList);
|
return mIndex != other.mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
inline bool operator==(const DeallocatingVectorIteratorState &other) {
|
||||||
return (mData == other.mData) && (mIndex == other.mIndex) && (mBucketList == other.mBucketList);
|
return mIndex == other.mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const DeallocatingVectorIteratorState &other) {
|
bool operator<(const DeallocatingVectorIteratorState &other) const {
|
||||||
return mIndex < other.mIndex;
|
return mIndex < other.mIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator>(const DeallocatingVectorIteratorState &other) const {
|
||||||
|
return mIndex > other.mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const DeallocatingVectorIteratorState &other) const {
|
||||||
|
return mIndex >= other.mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
//This is a hack to make assignment operator possible with reference member
|
//This is a hack to make assignment operator possible with reference member
|
||||||
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
inline DeallocatingVectorIteratorState& operator= (const DeallocatingVectorIteratorState &a) {
|
||||||
if (this != &a) {
|
if (this != &a) {
|
||||||
@@ -112,66 +99,69 @@ public:
|
|||||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||||
|
|
||||||
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
DeallocatingVectorIterator(std::size_t idx, std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
||||||
//DeallocatingVectorIterator(std::size_t idx, const std::vector<ElementT *> & input_list) : mState(idx, input_list) {}
|
|
||||||
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
DeallocatingVectorIterator(const DeallocatingVectorIteratorState & r) : mState(r) {}
|
||||||
|
|
||||||
template<typename T2>
|
template<typename T2>
|
||||||
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
DeallocatingVectorIterator& operator=(const DeallocatingVectorIterator<T2> &r) {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
mState = r.mState; return *this;
|
mState = r.mState; return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator++() { //prefix
|
inline DeallocatingVectorIterator& operator++() { //prefix
|
||||||
// if(DeallocateC) assert(false);
|
++mState.mIndex;
|
||||||
++mState.mIndex; mState.setPointerForIndex(); return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator--() { //prefix
|
inline DeallocatingVectorIterator& operator--() { //prefix
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
--mState.mIndex; mState.setPointerForIndex(); return *this;
|
--mState.mIndex;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator++(int) { //postfix
|
inline DeallocatingVectorIterator operator++(int) { //postfix
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
mState.mIndex++; mState.setPointerForIndex();
|
mState.mIndex++;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
inline DeallocatingVectorIterator operator --(int) { //postfix
|
inline DeallocatingVectorIterator operator--(int) { //postfix
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
mState.mIndex--; mState.setPointerForIndex();
|
mState.mIndex--;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
inline DeallocatingVectorIterator operator+(const difference_type& n) const {
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
_myState.mIndex+=n; _myState.setPointerForIndex();
|
_myState.mIndex+=n;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator+=(const difference_type& n) const {
|
inline DeallocatingVectorIterator& operator+=(const difference_type& n) {
|
||||||
mState.mIndex+=n; return *this;
|
mState.mIndex+=n; return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
inline DeallocatingVectorIterator operator-(const difference_type& n) const {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
DeallocatingVectorIteratorState _myState(mState);
|
||||||
_myState.mIndex-=n; _myState.setPointerForIndex();
|
_myState.mIndex-=n;
|
||||||
return DeallocatingVectorIterator(_myState);
|
return DeallocatingVectorIterator(_myState);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
inline DeallocatingVectorIterator& operator-=(const difference_type &n) const {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
mState.mIndex-=n; return *this;
|
mState.mIndex-=n; return *this;
|
||||||
}
|
}
|
||||||
inline reference operator*() const { return *mState.mData; }
|
|
||||||
inline pointer operator->() const { return mState.mData; }
|
inline reference operator*() const {
|
||||||
inline reference operator[](const difference_type &n) const {
|
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
||||||
if(DeallocateC) assert(false);
|
std::size_t _index = mState.mIndex%bucketSizeC;
|
||||||
DeallocatingVectorIteratorState _myState(mState);
|
return (mState.mBucketList[_bucket][_index]);
|
||||||
_myState.mIndex += n;
|
}
|
||||||
_myState.setPointerForIndex;
|
|
||||||
return _myState.mData;
|
inline pointer operator->() const {
|
||||||
|
std::size_t _bucket = mState.mIndex/bucketSizeC;
|
||||||
|
std::size_t _index = mState.mIndex%bucketSizeC;
|
||||||
|
return &(mState.mBucketList[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
inline bool operator!=(const DeallocatingVectorIterator & other) {
|
||||||
@@ -182,12 +172,20 @@ public:
|
|||||||
return mState == other.mState;
|
return mState == other.mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const DeallocatingVectorIterator & other) {
|
inline bool operator<(const DeallocatingVectorIterator & other) const {
|
||||||
return mState < other.mState;
|
return mState < other.mState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool operator>(const DeallocatingVectorIterator & other) const {
|
||||||
|
return mState > other.mState;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>=(const DeallocatingVectorIterator & other) const {
|
||||||
|
return mState >= other.mState;
|
||||||
|
}
|
||||||
|
|
||||||
difference_type operator-(const DeallocatingVectorIterator & other) {
|
difference_type operator-(const DeallocatingVectorIterator & other) {
|
||||||
if(DeallocateC) assert(false);
|
if(DeallocateC) BOOST_ASSERT(false);
|
||||||
return mState.mIndex-other.mState.mIndex;
|
return mState.mIndex-other.mState.mIndex;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef EDGE_BASED_NODE_H
|
||||||
|
#define EDGE_BASED_NODE_H
|
||||||
|
|
||||||
|
#include "Coordinate.h"
|
||||||
|
|
||||||
|
struct EdgeBasedNode {
|
||||||
|
EdgeBasedNode() :
|
||||||
|
id(INT_MAX),
|
||||||
|
lat1(INT_MAX),
|
||||||
|
lat2(INT_MAX),
|
||||||
|
lon1(INT_MAX),
|
||||||
|
lon2(INT_MAX >> 1),
|
||||||
|
belongsToTinyComponent(false),
|
||||||
|
nameID(UINT_MAX),
|
||||||
|
weight(UINT_MAX >> 1),
|
||||||
|
ignoreInGrid(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
|
return other.id < id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const EdgeBasedNode & other) const {
|
||||||
|
return id == other.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FixedPointCoordinate Centroid() const {
|
||||||
|
FixedPointCoordinate centroid;
|
||||||
|
//The coordinates of the midpoint are given by:
|
||||||
|
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
|
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
||||||
|
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isIgnored() const {
|
||||||
|
return ignoreInGrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID id;
|
||||||
|
int lat1;
|
||||||
|
int lat2;
|
||||||
|
int lon1;
|
||||||
|
int lon2:31;
|
||||||
|
bool belongsToTinyComponent:1;
|
||||||
|
NodeID nameID;
|
||||||
|
unsigned weight:31;
|
||||||
|
bool ignoreInGrid:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //EDGE_BASED_NODE_H
|
||||||
@@ -32,15 +32,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
|
||||||
struct _Node : NodeInfo{
|
struct ExternalMemoryNode : NodeInfo {
|
||||||
_Node(int _lat, int _lon, unsigned int _id, bool _bollard, bool _trafficLight) : NodeInfo(_lat, _lon, _id), bollard(_bollard), trafficLight(_trafficLight) {}
|
ExternalMemoryNode(
|
||||||
_Node() : bollard(false), trafficLight(false) {}
|
int lat,
|
||||||
|
int lon,
|
||||||
|
unsigned int id,
|
||||||
|
bool bollard,
|
||||||
|
bool traffic_light
|
||||||
|
) :
|
||||||
|
NodeInfo(lat, lon, id),
|
||||||
|
bollard(bollard),
|
||||||
|
trafficLight(traffic_light)
|
||||||
|
{ }
|
||||||
|
ExternalMemoryNode() : bollard(false), trafficLight(false) {}
|
||||||
|
|
||||||
static _Node min_value() {
|
static ExternalMemoryNode min_value() {
|
||||||
return _Node(0,0,0, false, false);
|
return ExternalMemoryNode(0,0,0, false, false);
|
||||||
}
|
}
|
||||||
static _Node max_value() {
|
static ExternalMemoryNode max_value() {
|
||||||
return _Node((std::numeric_limits<int>::max)(), (std::numeric_limits<int>::max)(), (std::numeric_limits<unsigned int>::max)(), false, false);
|
return ExternalMemoryNode(
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<int>::max(),
|
||||||
|
std::numeric_limits<unsigned>::max(),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
NodeID key() const {
|
NodeID key() const {
|
||||||
return id;
|
return id;
|
||||||
@@ -49,7 +65,7 @@ struct _Node : NodeInfo{
|
|||||||
bool trafficLight;
|
bool trafficLight;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImportNode : public _Node {
|
struct ImportNode : public ExternalMemoryNode {
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear() {
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline double y2lat(double a) {
|
inline double y2lat(double a) {
|
||||||
return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
|
return 180./M_PI * (2. * atan(exp(a*M_PI/180.)) - M_PI/2.);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double lat2y(double a) {
|
inline double lat2y(double a) {
|
||||||
return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
|
return 180./M_PI * log(tan(M_PI/4.+a*(M_PI/180.)/2.));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MERCATORUTIL_H_ */
|
#endif /* MERCATORUTIL_H_ */
|
||||||
|
|||||||
@@ -1,218 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NODEINFORMATIONHELPDESK_H_
|
|
||||||
#define NODEINFORMATIONHELPDESK_H_
|
|
||||||
|
|
||||||
#include "QueryNode.h"
|
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "StaticRTree.h"
|
|
||||||
#include "../Contractor/EdgeBasedGraphFactory.h"
|
|
||||||
#include "../Util/OSRMException.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
|
|
||||||
|
|
||||||
class NodeInformationHelpDesk : boost::noncopyable {
|
|
||||||
|
|
||||||
public:
|
|
||||||
NodeInformationHelpDesk(
|
|
||||||
const std::string & ram_index_filename,
|
|
||||||
const std::string & mem_index_filename,
|
|
||||||
const std::string & nodes_filename,
|
|
||||||
const std::string & edges_filename,
|
|
||||||
const unsigned m_number_of_nodes,
|
|
||||||
const unsigned m_check_sum
|
|
||||||
) :
|
|
||||||
m_number_of_nodes(m_number_of_nodes),
|
|
||||||
m_check_sum(m_check_sum)
|
|
||||||
{
|
|
||||||
if ( ram_index_filename.empty() ) {
|
|
||||||
throw OSRMException("no ram index file name in server ini");
|
|
||||||
}
|
|
||||||
if ( mem_index_filename.empty() ) {
|
|
||||||
throw OSRMException("no mem index file name in server ini");
|
|
||||||
}
|
|
||||||
if ( nodes_filename.empty() ) {
|
|
||||||
throw OSRMException("no nodes file name in server ini");
|
|
||||||
}
|
|
||||||
if ( edges_filename.empty() ) {
|
|
||||||
throw OSRMException("no edges file name in server ini");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ro_rtree_ptr = new StaticRTree<RTreeLeaf>(
|
|
||||||
ram_index_filename,
|
|
||||||
mem_index_filename
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
0 == m_coordinate_list.size(),
|
|
||||||
"Coordinate vector not empty"
|
|
||||||
);
|
|
||||||
|
|
||||||
LoadNodesAndEdges(nodes_filename, edges_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
~NodeInformationHelpDesk() {
|
|
||||||
delete m_ro_rtree_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FixedPointCoordinate GetCoordinateOfNode(const unsigned id) const {
|
|
||||||
const NodeID node = m_via_node_list.at(id);
|
|
||||||
return m_coordinate_list.at(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetNameIndexFromEdgeID(const unsigned id) const {
|
|
||||||
return m_name_ID_list.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const {
|
|
||||||
return m_turn_instruction_list.at(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline NodeID GetNumberOfNodes() const {
|
|
||||||
return m_number_of_nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool LocateClosestEndPointForCoordinate(
|
|
||||||
const FixedPointCoordinate& input_coordinate,
|
|
||||||
FixedPointCoordinate& result,
|
|
||||||
const unsigned zoom_level = 18
|
|
||||||
) const {
|
|
||||||
bool found_node = m_ro_rtree_ptr->LocateClosestEndPointForCoordinate(
|
|
||||||
input_coordinate,
|
|
||||||
result, zoom_level
|
|
||||||
);
|
|
||||||
return found_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool FindPhantomNodeForCoordinate(
|
|
||||||
const FixedPointCoordinate & input_coordinate,
|
|
||||||
PhantomNode & resulting_phantom_node,
|
|
||||||
const unsigned zoom_level
|
|
||||||
) const {
|
|
||||||
return m_ro_rtree_ptr->FindPhantomNodeForCoordinate(
|
|
||||||
input_coordinate,
|
|
||||||
resulting_phantom_node,
|
|
||||||
zoom_level
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetCheckSum() const {
|
|
||||||
return m_check_sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void LoadNodesAndEdges(
|
|
||||||
const std::string & nodes_filename,
|
|
||||||
const std::string & edges_filename
|
|
||||||
) {
|
|
||||||
boost::filesystem::path nodes_file(nodes_filename);
|
|
||||||
if ( !boost::filesystem::exists( nodes_file ) ) {
|
|
||||||
throw OSRMException("nodes file does not exist");
|
|
||||||
}
|
|
||||||
if ( 0 == boost::filesystem::file_size( nodes_file ) ) {
|
|
||||||
throw OSRMException("nodes file is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::path edges_file(edges_filename);
|
|
||||||
if ( !boost::filesystem::exists( edges_file ) ) {
|
|
||||||
throw OSRMException("edges file does not exist");
|
|
||||||
}
|
|
||||||
if ( 0 == boost::filesystem::file_size( edges_file ) ) {
|
|
||||||
throw OSRMException("edges file is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::ifstream nodes_input_stream(
|
|
||||||
nodes_file,
|
|
||||||
std::ios::binary
|
|
||||||
);
|
|
||||||
|
|
||||||
boost::filesystem::ifstream edges_input_stream(
|
|
||||||
edges_file, std::ios::binary
|
|
||||||
);
|
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG)
|
|
||||||
<< "Loading node data";
|
|
||||||
NodeInfo current_node;
|
|
||||||
while(!nodes_input_stream.eof()) {
|
|
||||||
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
|
||||||
m_coordinate_list.push_back(
|
|
||||||
FixedPointCoordinate(
|
|
||||||
current_node.lat,
|
|
||||||
current_node.lon
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
|
|
||||||
nodes_input_stream.close();
|
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG)
|
|
||||||
<< "Loading edge data";
|
|
||||||
unsigned number_of_edges = 0;
|
|
||||||
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
|
||||||
m_via_node_list.resize(number_of_edges);
|
|
||||||
m_name_ID_list.resize(number_of_edges);
|
|
||||||
m_turn_instruction_list.resize(number_of_edges);
|
|
||||||
|
|
||||||
OriginalEdgeData current_edge_data;
|
|
||||||
for(unsigned i = 0; i < number_of_edges; ++i) {
|
|
||||||
edges_input_stream.read(
|
|
||||||
(char*)&(current_edge_data),
|
|
||||||
sizeof(OriginalEdgeData)
|
|
||||||
);
|
|
||||||
m_via_node_list[i] = current_edge_data.viaNode;
|
|
||||||
m_name_ID_list[i] = current_edge_data.nameID;
|
|
||||||
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
|
|
||||||
}
|
|
||||||
edges_input_stream.close();
|
|
||||||
SimpleLogger().Write(logDEBUG)
|
|
||||||
<< "Loaded " << number_of_edges << " orig edges";
|
|
||||||
SimpleLogger().Write(logDEBUG)
|
|
||||||
<< "Opening NN indices";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<FixedPointCoordinate> m_coordinate_list;
|
|
||||||
std::vector<NodeID> m_via_node_list;
|
|
||||||
std::vector<unsigned> m_name_ID_list;
|
|
||||||
std::vector<TurnInstruction> m_turn_instruction_list;
|
|
||||||
|
|
||||||
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * m_ro_rtree_ptr;
|
|
||||||
const unsigned m_number_of_nodes;
|
|
||||||
const unsigned m_check_sum;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*NODEINFORMATIONHELPDESK_H_*/
|
|
||||||
@@ -99,10 +99,4 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NodesOfEdge {
|
|
||||||
NodeID edgeBasedNode;
|
|
||||||
double ratio;
|
|
||||||
FixedPointCoordinate projectedPoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* PHANTOMNODES_H_ */
|
#endif /* PHANTOMNODES_H_ */
|
||||||
|
|||||||
@@ -73,13 +73,13 @@ struct TurnRestriction {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _RawRestrictionContainer {
|
struct InputRestrictionContainer {
|
||||||
TurnRestriction restriction;
|
|
||||||
EdgeID fromWay;
|
EdgeID fromWay;
|
||||||
EdgeID toWay;
|
EdgeID toWay;
|
||||||
unsigned viaNode;
|
unsigned viaNode;
|
||||||
|
TurnRestriction restriction;
|
||||||
|
|
||||||
_RawRestrictionContainer(
|
InputRestrictionContainer(
|
||||||
EdgeID fromWay,
|
EdgeID fromWay,
|
||||||
EdgeID toWay,
|
EdgeID toWay,
|
||||||
NodeID vn,
|
NodeID vn,
|
||||||
@@ -91,7 +91,7 @@ struct _RawRestrictionContainer {
|
|||||||
{
|
{
|
||||||
restriction.viaNode = vn;
|
restriction.viaNode = vn;
|
||||||
}
|
}
|
||||||
_RawRestrictionContainer(
|
InputRestrictionContainer(
|
||||||
bool isOnly = false
|
bool isOnly = false
|
||||||
) :
|
) :
|
||||||
fromWay(UINT_MAX),
|
fromWay(UINT_MAX),
|
||||||
@@ -101,37 +101,45 @@ struct _RawRestrictionContainer {
|
|||||||
restriction.flags.isOnly = isOnly;
|
restriction.flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _RawRestrictionContainer min_value() {
|
static InputRestrictionContainer min_value() {
|
||||||
return _RawRestrictionContainer(0, 0, 0, 0);
|
return InputRestrictionContainer(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
static _RawRestrictionContainer max_value() {
|
static InputRestrictionContainer max_value() {
|
||||||
return _RawRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
return InputRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByFrom : public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
struct CmpRestrictionContainerByFrom :
|
||||||
typedef _RawRestrictionContainer value_type;
|
public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool>
|
||||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
{
|
||||||
|
typedef InputRestrictionContainer value_type;
|
||||||
|
inline bool operator()(
|
||||||
|
const InputRestrictionContainer & a,
|
||||||
|
const InputRestrictionContainer & b
|
||||||
|
) const {
|
||||||
return a.fromWay < b.fromWay;
|
return a.fromWay < b.fromWay;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
inline value_type max_value() const {
|
||||||
return _RawRestrictionContainer::max_value();
|
return InputRestrictionContainer::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
inline value_type min_value() const {
|
||||||
return _RawRestrictionContainer::min_value();
|
return InputRestrictionContainer::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
struct CmpRestrictionContainerByTo: public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool> {
|
||||||
typedef _RawRestrictionContainer value_type;
|
typedef InputRestrictionContainer value_type;
|
||||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
inline bool operator ()(
|
||||||
|
const InputRestrictionContainer & a,
|
||||||
|
const InputRestrictionContainer & b
|
||||||
|
) const {
|
||||||
return a.toWay < b.toWay;
|
return a.toWay < b.toWay;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() const {
|
||||||
return _RawRestrictionContainer::max_value();
|
return InputRestrictionContainer::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
value_type min_value() const {
|
||||||
return _RawRestrictionContainer::min_value();
|
return InputRestrictionContainer::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "SearchEngine.h"
|
|
||||||
|
|
||||||
SearchEngine::SearchEngine( QueryObjectsStorage * query_objects ) :
|
|
||||||
_queryData(query_objects),
|
|
||||||
shortestPath(_queryData),
|
|
||||||
alternativePaths(_queryData)
|
|
||||||
{}
|
|
||||||
|
|
||||||
SearchEngine::~SearchEngine() {}
|
|
||||||
|
|
||||||
void SearchEngine::GetCoordinatesForNodeID(
|
|
||||||
NodeID id,
|
|
||||||
FixedPointCoordinate& result
|
|
||||||
) const {
|
|
||||||
result = _queryData.nodeHelpDesk->GetCoordinateOfNode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchEngine::FindPhantomNodeForCoordinate(
|
|
||||||
const FixedPointCoordinate & location,
|
|
||||||
PhantomNode & result,
|
|
||||||
const unsigned zoomLevel
|
|
||||||
) const {
|
|
||||||
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
|
|
||||||
location,
|
|
||||||
result, zoomLevel
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
|
|
||||||
const NodeID s,
|
|
||||||
const NodeID t
|
|
||||||
) const {
|
|
||||||
if(s == t) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeID e = _queryData.graph->FindEdge(s, t);
|
|
||||||
if(e == UINT_MAX) {
|
|
||||||
e = _queryData.graph->FindEdge( t, s );
|
|
||||||
}
|
|
||||||
|
|
||||||
if(UINT_MAX == e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(e != UINT_MAX);
|
|
||||||
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
|
|
||||||
return ed.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
|
|
||||||
std::string result;
|
|
||||||
_queryData.query_objects->GetName(nameID, result);
|
|
||||||
return HTMLEntitize(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
|
||||||
SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
|
||||||
|
|
||||||
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
|
||||||
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
|
||||||
|
|
||||||
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
|
||||||
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
|
||||||
@@ -25,48 +25,43 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SEARCHENGINE_H_
|
#ifndef SEARCHENGINE_H
|
||||||
#define SEARCHENGINE_H_
|
#define SEARCHENGINE_H
|
||||||
|
|
||||||
#include "Coordinate.h"
|
#include "Coordinate.h"
|
||||||
#include "NodeInformationHelpDesk.h"
|
#include "SearchEngineData.h"
|
||||||
#include "PhantomNodes.h"
|
#include "PhantomNodes.h"
|
||||||
#include "QueryEdge.h"
|
#include "QueryEdge.h"
|
||||||
#include "SearchEngineData.h"
|
|
||||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
private:
|
private:
|
||||||
SearchEngineData _queryData;
|
DataFacadeT * facade;
|
||||||
|
SearchEngineData engine_working_data;
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting<SearchEngineData> shortestPath;
|
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||||
AlternativeRouting<SearchEngineData> alternativePaths;
|
AlternativeRouting <DataFacadeT> alternative_path;
|
||||||
|
|
||||||
SearchEngine( QueryObjectsStorage * query_objects );
|
SearchEngine( DataFacadeT * facade )
|
||||||
~SearchEngine();
|
:
|
||||||
|
facade (facade),
|
||||||
|
shortest_path (facade, engine_working_data),
|
||||||
|
alternative_path (facade, engine_working_data)
|
||||||
|
{}
|
||||||
|
|
||||||
void GetCoordinatesForNodeID(NodeID id, FixedPointCoordinate& result) const;
|
~SearchEngine() {}
|
||||||
|
|
||||||
void FindPhantomNodeForCoordinate(
|
|
||||||
const FixedPointCoordinate & location,
|
|
||||||
PhantomNode & result,
|
|
||||||
unsigned zoomLevel
|
|
||||||
) const;
|
|
||||||
|
|
||||||
NodeID GetNameIDForOriginDestinationNodeID(
|
|
||||||
const NodeID s, const NodeID t) const;
|
|
||||||
|
|
||||||
std::string GetEscapedNameForNameID(const unsigned nameID) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SEARCHENGINE_H_ */
|
#endif // SEARCHENGINE_H
|
||||||
|
|||||||
@@ -27,40 +27,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "SearchEngineData.h"
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) {
|
||||||
if(!forwardHeap.get()) {
|
if(!forwardHeap.get()) {
|
||||||
forwardHeap.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
forwardHeap->Clear();
|
forwardHeap->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap.get()) {
|
if(!backwardHeap.get()) {
|
||||||
backwardHeap.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
backwardHeap->Clear();
|
backwardHeap->Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
|
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) {
|
||||||
if(!forwardHeap2.get()) {
|
if(!forwardHeap2.get()) {
|
||||||
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
forwardHeap2->Clear();
|
forwardHeap2->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap2.get()) {
|
if(!backwardHeap2.get()) {
|
||||||
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
backwardHeap2->Clear();
|
backwardHeap2->Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
|
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) {
|
||||||
if(!forwardHeap3.get()) {
|
if(!forwardHeap3.get()) {
|
||||||
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
forwardHeap3->Clear();
|
forwardHeap3->Clear();
|
||||||
}
|
}
|
||||||
if(!backwardHeap3.get()) {
|
if(!backwardHeap3.get()) {
|
||||||
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->GetNumberOfNodes()));
|
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||||
} else {
|
} else {
|
||||||
backwardHeap3->Clear();
|
backwardHeap3->Clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef SEARCH_ENGINE_DATA_H
|
||||||
|
#define SEARCH_ENGINE_DATA_H
|
||||||
|
|
||||||
#include "BinaryHeap.h"
|
#include "BinaryHeap.h"
|
||||||
#include "QueryEdge.h"
|
#include "QueryEdge.h"
|
||||||
#include "StaticGraph.h"
|
#include "StaticGraph.h"
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
@@ -41,23 +43,12 @@ struct _HeapData {
|
|||||||
NodeID parent;
|
NodeID parent;
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
_HeapData( NodeID p ) : parent(p) { }
|
||||||
};
|
};
|
||||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
|
// typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
|
|
||||||
|
|
||||||
struct SearchEngineData {
|
struct SearchEngineData {
|
||||||
typedef QueryGraph Graph;
|
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeap;
|
||||||
typedef QueryHeapType QueryHeap;
|
typedef boost::thread_specific_ptr<QueryHeap> SearchEngineHeapPtr;
|
||||||
SearchEngineData(QueryObjectsStorage * query_objects)
|
|
||||||
:
|
|
||||||
query_objects(query_objects),
|
|
||||||
graph(query_objects->graph),
|
|
||||||
nodeHelpDesk(query_objects->nodeHelpDesk)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const QueryObjectsStorage * query_objects;
|
|
||||||
const QueryGraph * graph;
|
|
||||||
const NodeInformationHelpDesk * nodeHelpDesk;
|
|
||||||
|
|
||||||
static SearchEngineHeapPtr forwardHeap;
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
static SearchEngineHeapPtr backwardHeap;
|
static SearchEngineHeapPtr backwardHeap;
|
||||||
@@ -66,9 +57,11 @@ struct SearchEngineData {
|
|||||||
static SearchEngineHeapPtr forwardHeap3;
|
static SearchEngineHeapPtr forwardHeap3;
|
||||||
static SearchEngineHeapPtr backwardHeap3;
|
static SearchEngineHeapPtr backwardHeap3;
|
||||||
|
|
||||||
void InitializeOrClearFirstThreadLocalStorage();
|
void InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
|
||||||
void InitializeOrClearSecondThreadLocalStorage();
|
void InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
|
|
||||||
void InitializeOrClearThirdThreadLocalStorage();
|
void InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // SEARCH_ENGINE_DATA_H
|
||||||
|
|||||||
@@ -0,0 +1,250 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARED_MEMORY_FACTORY_H
|
||||||
|
#define SHARED_MEMORY_FACTORY_H
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/ipc.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
struct OSRMLockFile {
|
||||||
|
boost::filesystem::path operator()() {
|
||||||
|
boost::filesystem::path temp_dir =
|
||||||
|
boost::filesystem::temp_directory_path();
|
||||||
|
boost::filesystem::path lock_file = temp_dir / "osrm.lock";
|
||||||
|
return lock_file;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SharedMemory : boost::noncopyable {
|
||||||
|
|
||||||
|
//Remove shared memory on destruction
|
||||||
|
class shm_remove : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
int m_shmid;
|
||||||
|
bool m_initialized;
|
||||||
|
public:
|
||||||
|
void SetID(int shmid) {
|
||||||
|
m_shmid = shmid;
|
||||||
|
m_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
shm_remove() : m_shmid(INT_MIN), m_initialized(false) {}
|
||||||
|
|
||||||
|
~shm_remove(){
|
||||||
|
if(m_initialized) {
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"automatic memory deallocation";
|
||||||
|
if(!boost::interprocess::xsi_shared_memory::remove(m_shmid)) {
|
||||||
|
SimpleLogger().Write(logDEBUG) << "could not deallocate id " << m_shmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void * Ptr() const {
|
||||||
|
return region.get_address();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
SharedMemory(
|
||||||
|
const boost::filesystem::path & lock_file,
|
||||||
|
const IdentifierT id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true
|
||||||
|
) : key(
|
||||||
|
lock_file.string().c_str(),
|
||||||
|
id
|
||||||
|
) {
|
||||||
|
if( 0 == size ){ //read_only
|
||||||
|
shm = boost::interprocess::xsi_shared_memory (
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key
|
||||||
|
);
|
||||||
|
|
||||||
|
region = boost::interprocess::mapped_region (
|
||||||
|
shm,
|
||||||
|
(
|
||||||
|
read_write ?
|
||||||
|
boost::interprocess::read_write :
|
||||||
|
boost::interprocess::read_only
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else { //writeable pointer
|
||||||
|
//remove previously allocated mem
|
||||||
|
if( remove_prev ) {
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
shm = boost::interprocess::xsi_shared_memory (
|
||||||
|
boost::interprocess::open_or_create,
|
||||||
|
key,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
#ifdef __linux__
|
||||||
|
if( -1 == shmctl(shm.get_shmid(), SHM_LOCK, 0) ) {
|
||||||
|
if( ENOMEM == errno ) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"could not lock shared memory to RAM";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
region = boost::interprocess::mapped_region (
|
||||||
|
shm,
|
||||||
|
boost::interprocess::read_write
|
||||||
|
);
|
||||||
|
|
||||||
|
remover.SetID( shm.get_shmid() );
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"writeable memory allocated " << size << " bytes";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
static bool RegionExists(
|
||||||
|
const IdentifierT id
|
||||||
|
) {
|
||||||
|
bool result = true;
|
||||||
|
try {
|
||||||
|
OSRMLockFile lock_file;
|
||||||
|
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
||||||
|
result = RegionExists(key);
|
||||||
|
} catch(...) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
static bool Remove(
|
||||||
|
const IdentifierT id
|
||||||
|
) {
|
||||||
|
OSRMLockFile lock_file;
|
||||||
|
boost::interprocess::xsi_key key( lock_file().string().c_str(), id );
|
||||||
|
return Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool RegionExists( const boost::interprocess::xsi_key &key ) {
|
||||||
|
bool result = true;
|
||||||
|
try {
|
||||||
|
boost::interprocess::xsi_shared_memory shm(
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key
|
||||||
|
);
|
||||||
|
} catch(...) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Remove(
|
||||||
|
const boost::interprocess::xsi_key &key
|
||||||
|
) {
|
||||||
|
bool ret = false;
|
||||||
|
try{
|
||||||
|
SimpleLogger().Write(logDEBUG) << "deallocating prev memory";
|
||||||
|
boost::interprocess::xsi_shared_memory xsi(
|
||||||
|
boost::interprocess::open_only,
|
||||||
|
key
|
||||||
|
);
|
||||||
|
ret = boost::interprocess::xsi_shared_memory::remove(xsi.get_shmid());
|
||||||
|
} catch(const boost::interprocess::interprocess_exception &e){
|
||||||
|
if(e.get_error_code() != boost::interprocess::not_found_error) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::interprocess::xsi_key key;
|
||||||
|
boost::interprocess::xsi_shared_memory shm;
|
||||||
|
boost::interprocess::mapped_region region;
|
||||||
|
shm_remove remover;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class LockFileT = OSRMLockFile>
|
||||||
|
class SharedMemoryFactory_tmpl : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename IdentifierT >
|
||||||
|
static SharedMemory * Get(
|
||||||
|
const IdentifierT & id,
|
||||||
|
const uint64_t size = 0,
|
||||||
|
bool read_write = false,
|
||||||
|
bool remove_prev = true
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
LockFileT lock_file;
|
||||||
|
if(!boost::filesystem::exists(lock_file()) ) {
|
||||||
|
if( 0 == size ) {
|
||||||
|
throw OSRMException("lock file does not exist, exiting");
|
||||||
|
} else {
|
||||||
|
boost::filesystem::ofstream ofs(lock_file());
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new SharedMemory(
|
||||||
|
lock_file(),
|
||||||
|
id,
|
||||||
|
size,
|
||||||
|
read_write,
|
||||||
|
remove_prev
|
||||||
|
);
|
||||||
|
} catch(const boost::interprocess::interprocess_exception &e){
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"caught exception: " << e.what() <<
|
||||||
|
", code " << e.get_error_code();
|
||||||
|
throw OSRMException(e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharedMemoryFactory_tmpl() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef SharedMemoryFactory_tmpl<> SharedMemoryFactory;
|
||||||
|
|
||||||
|
#endif /* SHARED_MEMORY_POINTER_FACTORY_H */
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
#define SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<typename DataT>
|
||||||
|
class ShMemIterator : public std::iterator<std::input_iterator_tag, DataT> {
|
||||||
|
DataT * p;
|
||||||
|
public:
|
||||||
|
ShMemIterator(DataT * x) : p(x) {}
|
||||||
|
ShMemIterator(const ShMemIterator & mit) : p(mit.p) {}
|
||||||
|
ShMemIterator& operator++() {
|
||||||
|
++p;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
ShMemIterator operator++(int) {
|
||||||
|
ShMemIterator tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
ShMemIterator operator+(std::ptrdiff_t diff) {
|
||||||
|
ShMemIterator tmp(p+diff);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
bool operator==(const ShMemIterator& rhs) {
|
||||||
|
return p==rhs.p;
|
||||||
|
}
|
||||||
|
bool operator!=(const ShMemIterator& rhs) {
|
||||||
|
return p!=rhs.p;
|
||||||
|
}
|
||||||
|
DataT& operator*() {
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DataT>
|
||||||
|
class SharedMemoryWrapper {
|
||||||
|
private:
|
||||||
|
DataT * m_ptr;
|
||||||
|
std::size_t m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SharedMemoryWrapper() :
|
||||||
|
m_ptr(NULL),
|
||||||
|
m_size(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
SharedMemoryWrapper(DataT * ptr, std::size_t size) :
|
||||||
|
m_ptr(ptr),
|
||||||
|
m_size(size)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void swap( SharedMemoryWrapper<DataT> & other ) {
|
||||||
|
BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid");
|
||||||
|
std::swap( m_size, other.m_size);
|
||||||
|
std::swap( m_ptr , other.m_ptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// void SetData(const DataT * ptr, const std::size_t size) {
|
||||||
|
// BOOST_ASSERT_MSG( 0 == m_size, "vector not empty");
|
||||||
|
// BOOST_ASSERT_MSG( 0 < size , "new vector empty");
|
||||||
|
// m_ptr.reset(ptr);
|
||||||
|
// m_size = size;
|
||||||
|
// }
|
||||||
|
|
||||||
|
DataT & at(const std::size_t index) {
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataT & at(const std::size_t index) const {
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
ShMemIterator<DataT> begin() const {
|
||||||
|
return ShMemIterator<DataT>(m_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShMemIterator<DataT> end() const {
|
||||||
|
return ShMemIterator<DataT>(m_ptr+m_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t size() const { return m_size; }
|
||||||
|
|
||||||
|
DataT & operator[](const unsigned index) {
|
||||||
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DataT & operator[](const unsigned index) const {
|
||||||
|
BOOST_ASSERT_MSG(index < m_size, "invalid size");
|
||||||
|
return m_ptr[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename DataT, bool UseSharedMemory>
|
||||||
|
struct ShM {
|
||||||
|
typedef typename boost::conditional<
|
||||||
|
UseSharedMemory,
|
||||||
|
SharedMemoryWrapper<DataT>,
|
||||||
|
std::vector<DataT>
|
||||||
|
>::type vector;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //SHARED_MEMORY_VECTOR_WRAPPER_H
|
||||||
@@ -29,13 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define STATICGRAPH_H_INCLUDED
|
#define STATICGRAPH_H_INCLUDED
|
||||||
|
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
|
#include "../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
template< typename EdgeDataT, bool UseSharedMemory = false>
|
||||||
class StaticGraph {
|
class StaticGraph {
|
||||||
public:
|
public:
|
||||||
typedef NodeID NodeIterator;
|
typedef NodeID NodeIterator;
|
||||||
@@ -47,8 +48,9 @@ public:
|
|||||||
NodeIterator source;
|
NodeIterator source;
|
||||||
NodeIterator target;
|
NodeIterator target;
|
||||||
bool operator<( const InputEdge& right ) const {
|
bool operator<( const InputEdge& right ) const {
|
||||||
if ( source != right.source )
|
if ( source != right.source ) {
|
||||||
return source < right.source;
|
return source < right.source;
|
||||||
|
}
|
||||||
return target < right.target;
|
return target < right.target;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -89,16 +91,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticGraph( std::vector<_StrNode> & nodes, std::vector<_StrEdge> & edges) {
|
StaticGraph(
|
||||||
_numNodes = nodes.size();
|
typename ShM<_StrNode, UseSharedMemory>::vector & nodes,
|
||||||
|
typename ShM<_StrEdge, UseSharedMemory>::vector & edges
|
||||||
|
) {
|
||||||
|
_numNodes = nodes.size()-1;
|
||||||
_numEdges = edges.size();
|
_numEdges = edges.size();
|
||||||
|
|
||||||
_nodes.swap(nodes);
|
_nodes.swap(nodes);
|
||||||
_edges.swap(edges);
|
_edges.swap(edges);
|
||||||
|
|
||||||
//Add dummy node to end of _nodes array;
|
|
||||||
_nodes.push_back(_nodes.back());
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
Percent p(GetNumberOfNodes());
|
Percent p(GetNumberOfNodes());
|
||||||
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
|
for(unsigned u = 0; u < GetNumberOfNodes(); ++u) {
|
||||||
@@ -136,32 +138,32 @@ public:
|
|||||||
return _numEdges;
|
return _numEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator &n ) const {
|
unsigned GetOutDegree( const NodeIterator n ) const {
|
||||||
return BeginEdges(n)-EndEdges(n) - 1;
|
return BeginEdges(n)-EndEdges(n) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NodeIterator GetTarget( const EdgeIterator &e ) const {
|
inline NodeIterator GetTarget( const EdgeIterator e ) const {
|
||||||
return NodeIterator( _edges[e].target );
|
return NodeIterator( _edges[e].target );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline EdgeDataT &GetEdgeData( const EdgeIterator &e ) {
|
inline EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
||||||
return _edges[e].data;
|
return _edges[e].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const {
|
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
||||||
return _edges[e].data;
|
return _edges[e].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator &n ) const {
|
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||||
return EdgeIterator( _nodes[n].firstEdge );
|
return EdgeIterator( _nodes[n].firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator &n ) const {
|
EdgeIterator EndEdges( const NodeIterator n ) const {
|
||||||
return EdgeIterator( _nodes[n+1].firstEdge );
|
return EdgeIterator( _nodes[n+1].firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
//searches for a specific edge
|
//searches for a specific edge
|
||||||
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const {
|
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||||
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||||
EdgeWeight smallestWeight = UINT_MAX;
|
EdgeWeight smallestWeight = UINT_MAX;
|
||||||
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) {
|
||||||
@@ -174,17 +176,18 @@ public:
|
|||||||
return smallestEdge;
|
return smallestEdge;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeInEitherDirection( const NodeIterator &from, const NodeIterator &to ) const {
|
EdgeIterator FindEdgeInEitherDirection( const NodeIterator from, const NodeIterator to ) const {
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
EdgeIterator tmp = FindEdge( from, to );
|
||||||
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
return (UINT_MAX != tmp ? tmp : FindEdge( to, from ));
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator &from, const NodeIterator &to, bool & result ) const {
|
EdgeIterator FindEdgeIndicateIfReverse( const NodeIterator from, const NodeIterator to, bool & result ) const {
|
||||||
EdgeIterator tmp = FindEdge( from, to );
|
EdgeIterator tmp = FindEdge( from, to );
|
||||||
if(UINT_MAX == tmp) {
|
if(UINT_MAX == tmp) {
|
||||||
tmp = FindEdge( to, from );
|
tmp = FindEdge( to, from );
|
||||||
if(UINT_MAX != tmp)
|
if(UINT_MAX != tmp) {
|
||||||
result = true;
|
result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
@@ -194,8 +197,8 @@ private:
|
|||||||
NodeIterator _numNodes;
|
NodeIterator _numNodes;
|
||||||
EdgeIterator _numEdges;
|
EdgeIterator _numEdges;
|
||||||
|
|
||||||
std::vector< _StrNode > _nodes;
|
typename ShM< _StrNode, UseSharedMemory >::vector _nodes;
|
||||||
std::vector< _StrEdge > _edges;
|
typename ShM< _StrEdge, UseSharedMemory >::vector _edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // STATICGRAPH_H_INCLUDED
|
#endif // STATICGRAPH_H_INCLUDED
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef STATICKDTREE_H_INCLUDED
|
#ifndef STATICKDTREE_H_INCLUDED
|
||||||
#define STATICKDTREE_H_INCLUDED
|
#define STATICKDTREE_H_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
#include <boost/assert.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
@@ -100,8 +100,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
StaticKDTree( std::vector< InputPoint > * points ){
|
StaticKDTree( std::vector< InputPoint > * points ){
|
||||||
assert( k > 0 );
|
BOOST_ASSERT( k > 0 );
|
||||||
assert ( points->size() > 0 );
|
BOOST_ASSERT ( points->size() > 0 );
|
||||||
size = points->size();
|
size = points->size();
|
||||||
kdtree = new InputPoint[size];
|
kdtree = new InputPoint[size];
|
||||||
for ( Iterator i = 0; i != size; ++i ) {
|
for ( Iterator i = 0; i != size; ++i ) {
|
||||||
@@ -209,11 +209,11 @@ private:
|
|||||||
public:
|
public:
|
||||||
Less( unsigned d ) {
|
Less( unsigned d ) {
|
||||||
dimension = d;
|
dimension = d;
|
||||||
assert( dimension < k );
|
BOOST_ASSERT( dimension < k );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
bool operator() ( const InputPoint& left, const InputPoint& right ) {
|
||||||
assert( dimension < k );
|
BOOST_ASSERT( dimension < k );
|
||||||
return left.coordinates[dimension] < right.coordinates[dimension];
|
return left.coordinates[dimension] < right.coordinates[dimension];
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -28,11 +28,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef STATICRTREE_H_
|
#ifndef STATICRTREE_H_
|
||||||
#define STATICRTREE_H_
|
#define STATICRTREE_H_
|
||||||
|
|
||||||
#include "MercatorUtil.h"
|
|
||||||
#include "Coordinate.h"
|
#include "Coordinate.h"
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "DeallocatingVector.h"
|
#include "DeallocatingVector.h"
|
||||||
#include "HilbertValue.h"
|
#include "HilbertValue.h"
|
||||||
|
#include "MercatorUtil.h"
|
||||||
|
#include "PhantomNodes.h"
|
||||||
|
#include "SharedMemoryFactory.h"
|
||||||
|
#include "SharedMemoryVectorWrapper.h"
|
||||||
|
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
@@ -48,6 +51,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/range/algorithm_ext/erase.hpp>
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/type_traits.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -63,9 +67,9 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
|
|||||||
|
|
||||||
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
|
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
|
||||||
|
|
||||||
template<class DataT>
|
template<class DataT, bool UseSharedMemory = false>
|
||||||
class StaticRTree : boost::noncopyable {
|
class StaticRTree : boost::noncopyable {
|
||||||
private:
|
public:
|
||||||
struct RectangleInt2D {
|
struct RectangleInt2D {
|
||||||
RectangleInt2D() :
|
RectangleInt2D() :
|
||||||
min_lon(INT_MAX),
|
min_lon(INT_MAX),
|
||||||
@@ -237,6 +241,16 @@ private:
|
|||||||
|
|
||||||
typedef RectangleInt2D RectangleT;
|
typedef RectangleInt2D RectangleT;
|
||||||
|
|
||||||
|
struct TreeNode {
|
||||||
|
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
||||||
|
RectangleT minimum_bounding_rectangle;
|
||||||
|
uint32_t child_count:31;
|
||||||
|
bool child_is_on_disk:1;
|
||||||
|
uint32_t children[RTREE_BRANCHING_FACTOR];
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
struct WrappedInputElement {
|
struct WrappedInputElement {
|
||||||
explicit WrappedInputElement(
|
explicit WrappedInputElement(
|
||||||
const uint32_t _array_index,
|
const uint32_t _array_index,
|
||||||
@@ -259,14 +273,6 @@ private:
|
|||||||
DataT objects[RTREE_LEAF_NODE_SIZE];
|
DataT objects[RTREE_LEAF_NODE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TreeNode {
|
|
||||||
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
|
||||||
RectangleT minimum_bounding_rectangle;
|
|
||||||
uint32_t child_count:31;
|
|
||||||
bool child_is_on_disk:1;
|
|
||||||
uint32_t children[RTREE_BRANCHING_FACTOR];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QueryCandidate {
|
struct QueryCandidate {
|
||||||
explicit QueryCandidate(
|
explicit QueryCandidate(
|
||||||
const uint32_t n_id,
|
const uint32_t n_id,
|
||||||
@@ -280,7 +286,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<TreeNode> m_search_tree;
|
typename ShM<TreeNode, UseSharedMemory>::vector m_search_tree;
|
||||||
uint64_t m_element_count;
|
uint64_t m_element_count;
|
||||||
|
|
||||||
const std::string m_leaf_node_filename;
|
const std::string m_leaf_node_filename;
|
||||||
@@ -414,11 +420,10 @@ public:
|
|||||||
|
|
||||||
//Read-only operation for queries
|
//Read-only operation for queries
|
||||||
explicit StaticRTree(
|
explicit StaticRTree(
|
||||||
const std::string & node_filename,
|
const boost::filesystem::path & node_file,
|
||||||
const std::string & leaf_filename
|
const boost::filesystem::path & leaf_file
|
||||||
) : m_leaf_node_filename(leaf_filename) {
|
) : m_leaf_node_filename(leaf_file.string()) {
|
||||||
//open tree node file and load into RAM.
|
//open tree node file and load into RAM.
|
||||||
boost::filesystem::path node_file(node_filename);
|
|
||||||
|
|
||||||
if ( !boost::filesystem::exists( node_file ) ) {
|
if ( !boost::filesystem::exists( node_file ) ) {
|
||||||
throw OSRMException("ram index file does not exist");
|
throw OSRMException("ram index file does not exist");
|
||||||
@@ -434,9 +439,7 @@ public:
|
|||||||
m_search_tree.resize(tree_size);
|
m_search_tree.resize(tree_size);
|
||||||
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
||||||
tree_node_file.close();
|
tree_node_file.close();
|
||||||
|
|
||||||
//open leaf node file and store thread specific pointer
|
//open leaf node file and store thread specific pointer
|
||||||
boost::filesystem::path leaf_file(leaf_filename);
|
|
||||||
if ( !boost::filesystem::exists( leaf_file ) ) {
|
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||||
throw OSRMException("mem index file does not exist");
|
throw OSRMException("mem index file does not exist");
|
||||||
}
|
}
|
||||||
@@ -451,6 +454,34 @@ public:
|
|||||||
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||||
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit StaticRTree(
|
||||||
|
TreeNode * tree_node_ptr,
|
||||||
|
const uint32_t number_of_nodes,
|
||||||
|
const boost::filesystem::path & leaf_file
|
||||||
|
) : m_search_tree(tree_node_ptr, number_of_nodes),
|
||||||
|
m_leaf_node_filename(leaf_file.string())
|
||||||
|
{
|
||||||
|
//open leaf node file and store thread specific pointer
|
||||||
|
if ( !boost::filesystem::exists( leaf_file ) ) {
|
||||||
|
throw OSRMException("mem index file does not exist");
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( leaf_file ) ) {
|
||||||
|
throw OSRMException("mem index file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::ifstream leaf_node_file( leaf_file, std::ios::binary );
|
||||||
|
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
|
||||||
|
leaf_node_file.close();
|
||||||
|
|
||||||
|
if( thread_local_rtree_stream.get() ) {
|
||||||
|
thread_local_rtree_stream->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||||
|
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||||
|
}
|
||||||
|
//Read-only operation for queries
|
||||||
/*
|
/*
|
||||||
inline void FindKNearestPhantomNodesForCoordinate(
|
inline void FindKNearestPhantomNodesForCoordinate(
|
||||||
const FixedPointCoordinate & location,
|
const FixedPointCoordinate & location,
|
||||||
|
|||||||
@@ -31,33 +31,42 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../DataStructures/RawRouteData.h"
|
#include "../DataStructures/RawRouteData.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../Server/Http/Reply.h"
|
||||||
#include "../Server/BasicDatastructures.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct _DescriptorConfig {
|
struct DescriptorConfig {
|
||||||
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
|
DescriptorConfig() :
|
||||||
|
instructions(true),
|
||||||
|
geometry(true),
|
||||||
|
encode_geometry(true),
|
||||||
|
zoom_level(18)
|
||||||
|
{ }
|
||||||
bool instructions;
|
bool instructions;
|
||||||
bool geometry;
|
bool geometry;
|
||||||
bool encodeGeometry;
|
bool encode_geometry;
|
||||||
unsigned short z;
|
unsigned short zoom_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class BaseDescriptor {
|
class BaseDescriptor {
|
||||||
public:
|
public:
|
||||||
BaseDescriptor() { }
|
BaseDescriptor() { }
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BaseDescriptor() { }
|
virtual ~BaseDescriptor() { }
|
||||||
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
|
virtual void Run(
|
||||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
http::Reply & reply,
|
||||||
|
const RawRouteData &rawRoute,
|
||||||
|
PhantomNodes &phantomNodes,
|
||||||
|
const DataFacadeT * facade
|
||||||
|
) = 0;
|
||||||
|
virtual void SetConfig(const DescriptorConfig & config) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASE_DESCRIPTOR_H_ */
|
#endif /* BASE_DESCRIPTOR_H_ */
|
||||||
|
|||||||
+182
-149
@@ -45,31 +45,47 @@ double DescriptionFactory::GetBearing(
|
|||||||
) const {
|
) const {
|
||||||
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||||
|
|
||||||
double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||||
double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
double y = sin(deltaLong) * cos(lat2);
|
const double y = sin(deltaLong) * cos(lat2);
|
||||||
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
||||||
double result = RadianToDegree(atan2(y, x));
|
double result = RadianToDegree(atan2(y, x));
|
||||||
while(result <= 0.)
|
while(result < 0.) {
|
||||||
result += 360.;
|
result += 360.;
|
||||||
while(result >= 360.)
|
}
|
||||||
|
while(result >= 360.) {
|
||||||
result -= 360.;
|
result -= 360.;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
|
void DescriptionFactory::SetStartSegment(const PhantomNode & sph) {
|
||||||
startPhantom = _startPhantom;
|
start_phantom = sph;
|
||||||
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
|
AppendSegment(
|
||||||
|
sph.location,
|
||||||
|
_PathData(0, sph.nodeBasedEdgeNameID, 10, sph.weight1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
|
void DescriptionFactory::SetEndSegment(const PhantomNode & tph) {
|
||||||
targetPhantom = _targetPhantom;
|
target_phantom = tph;
|
||||||
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
|
pathDescription.push_back(
|
||||||
|
SegmentInformation(
|
||||||
|
tph.location,
|
||||||
|
tph.nodeBasedEdgeNameID,
|
||||||
|
0,
|
||||||
|
tph.weight1,
|
||||||
|
0,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data ) {
|
void DescriptionFactory::AppendSegment(
|
||||||
|
const FixedPointCoordinate & coordinate,
|
||||||
|
const _PathData & data
|
||||||
|
) {
|
||||||
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
||||||
pathDescription.back().nameID = data.nameID;
|
pathDescription.back().nameID = data.nameID;
|
||||||
} else {
|
} else {
|
||||||
@@ -77,144 +93,161 @@ void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
|
void DescriptionFactory::AppendEncodedPolylineString(
|
||||||
if(isEncoded)
|
const bool return_encoded,
|
||||||
pc.printEncodedString(pathDescription, output);
|
std::vector<std::string> & output
|
||||||
else
|
) {
|
||||||
pc.printUnencodedString(pathDescription, output);
|
std::string temp;
|
||||||
}
|
if(return_encoded) {
|
||||||
|
polyline_compressor.printEncodedString(pathDescription, temp);
|
||||||
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
|
|
||||||
pc.printEncodedString(pathDescription, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
|
|
||||||
pc.printUnencodedString(pathDescription, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
|
||||||
|
|
||||||
if(0 == pathDescription.size())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// unsigned entireLength = 0;
|
|
||||||
/** starts at index 1 */
|
|
||||||
pathDescription[0].length = 0;
|
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
|
||||||
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
|
||||||
}
|
|
||||||
|
|
||||||
double lengthOfSegment = 0;
|
|
||||||
unsigned durationOfSegment = 0;
|
|
||||||
unsigned indexOfSegmentBegin = 0;
|
|
||||||
|
|
||||||
std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
|
|
||||||
std::string string1;
|
|
||||||
|
|
||||||
|
|
||||||
/*Simplify turn instructions
|
|
||||||
Input :
|
|
||||||
10. Turn left on B 36 for 20 km
|
|
||||||
11. Continue on B 35; B 36 for 2 km
|
|
||||||
12. Continue on B 36 for 13 km
|
|
||||||
|
|
||||||
becomes:
|
|
||||||
10. Turn left on B 36 for 35 km
|
|
||||||
*/
|
|
||||||
//TODO: rework to check only end and start of string.
|
|
||||||
// stl string is way to expensive
|
|
||||||
|
|
||||||
// unsigned lastTurn = 0;
|
|
||||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
|
||||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
|
||||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
|
||||||
// if(std::string::npos != string0.find(string1+";")
|
|
||||||
// || std::string::npos != string0.find(";"+string1)
|
|
||||||
// || std::string::npos != string0.find(string1+" ;")
|
|
||||||
// || std::string::npos != string0.find("; "+string1)
|
|
||||||
// ){
|
|
||||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
|
||||||
// for(; lastTurn != i; ++lastTurn)
|
|
||||||
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
|
||||||
// } else if(std::string::npos != string1.find(string0+";")
|
|
||||||
// || std::string::npos != string1.find(";"+string0)
|
|
||||||
// || std::string::npos != string1.find(string0+" ;")
|
|
||||||
// || std::string::npos != string1.find("; "+string0)
|
|
||||||
// ){
|
|
||||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
|
||||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
|
||||||
// lastTurn = i;
|
|
||||||
// }
|
|
||||||
// string0 = string1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
|
||||||
entireLength += pathDescription[i].length;
|
|
||||||
lengthOfSegment += pathDescription[i].length;
|
|
||||||
durationOfSegment += pathDescription[i].duration;
|
|
||||||
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
|
||||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
|
||||||
|
|
||||||
|
|
||||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
|
||||||
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
|
|
||||||
assert(pathDescription[i].necessary);
|
|
||||||
lengthOfSegment = 0;
|
|
||||||
durationOfSegment = 0;
|
|
||||||
indexOfSegmentBegin = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
|
||||||
|
|
||||||
//Post-processing to remove empty or nearly empty path segments
|
|
||||||
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
|
||||||
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
|
|
||||||
if(pathDescription.size() > 2){
|
|
||||||
pathDescription.pop_back();
|
|
||||||
pathDescription.back().necessary = true;
|
|
||||||
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
|
||||||
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
|
||||||
// SimpleLogger().Write() << "Deleting last turn instruction";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
|
polyline_compressor.printUnencodedString(pathDescription, temp);
|
||||||
}
|
}
|
||||||
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
output.push_back(temp);
|
||||||
//TODO: this is never called actually?
|
|
||||||
if(pathDescription.size() > 2) {
|
|
||||||
pathDescription.erase(pathDescription.begin());
|
|
||||||
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
|
||||||
pathDescription[0].necessary = true;
|
|
||||||
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
|
||||||
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pathDescription[0].duration *= startPhantom.ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Generalize poly line
|
|
||||||
dp.Run(pathDescription, zoomLevel);
|
|
||||||
|
|
||||||
//fix what needs to be fixed else
|
|
||||||
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
|
||||||
if(pathDescription[i].necessary) {
|
|
||||||
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
|
||||||
pathDescription[i].bearing = angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildRouteSummary(entireLength, duration);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time) {
|
void DescriptionFactory::AppendEncodedPolylineString(
|
||||||
summary.startName = startPhantom.nodeBasedEdgeNameID;
|
std::vector<std::string> &output
|
||||||
summary.destName = targetPhantom.nodeBasedEdgeNameID;
|
) const {
|
||||||
|
std::string temp;
|
||||||
|
polyline_compressor.printEncodedString(pathDescription, temp);
|
||||||
|
output.push_back(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendUnencodedPolylineString(
|
||||||
|
std::vector<std::string>& output
|
||||||
|
) const {
|
||||||
|
std::string temp;
|
||||||
|
polyline_compressor.printUnencodedString(pathDescription, temp);
|
||||||
|
output.push_back(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
||||||
|
|
||||||
|
// if(0 == pathDescription.size())
|
||||||
|
// return;
|
||||||
|
|
||||||
|
// // unsigned entireLength = 0;
|
||||||
|
// /** starts at index 1 */
|
||||||
|
// pathDescription[0].length = 0;
|
||||||
|
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// double lengthOfSegment = 0;
|
||||||
|
// unsigned durationOfSegment = 0;
|
||||||
|
// unsigned indexOfSegmentBegin = 0;
|
||||||
|
|
||||||
|
// std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
|
||||||
|
// std::string string1;
|
||||||
|
|
||||||
|
|
||||||
|
// /*Simplify turn instructions
|
||||||
|
// Input :
|
||||||
|
// 10. Turn left on B 36 for 20 km
|
||||||
|
// 11. Continue on B 35; B 36 for 2 km
|
||||||
|
// 12. Continue on B 36 for 13 km
|
||||||
|
|
||||||
|
// becomes:
|
||||||
|
// 10. Turn left on B 36 for 35 km
|
||||||
|
// */
|
||||||
|
// //TODO: rework to check only end and start of string.
|
||||||
|
// // stl string is way to expensive
|
||||||
|
|
||||||
|
// // unsigned lastTurn = 0;
|
||||||
|
// // for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// // string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||||
|
// // if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||||
|
// // if(std::string::npos != string0.find(string1+";")
|
||||||
|
// // || std::string::npos != string0.find(";"+string1)
|
||||||
|
// // || std::string::npos != string0.find(string1+" ;")
|
||||||
|
// // || std::string::npos != string0.find("; "+string1)
|
||||||
|
// // ){
|
||||||
|
// // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||||
|
// // for(; lastTurn != i; ++lastTurn)
|
||||||
|
// // pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||||
|
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// // } else if(std::string::npos != string1.find(string0+";")
|
||||||
|
// // || std::string::npos != string1.find(";"+string0)
|
||||||
|
// // || std::string::npos != string1.find(string0+" ;")
|
||||||
|
// // || std::string::npos != string1.find("; "+string0)
|
||||||
|
// // ){
|
||||||
|
// // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||||
|
// // pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||||
|
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
// // lastTurn = i;
|
||||||
|
// // }
|
||||||
|
// // string0 = string1;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
|
||||||
|
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// entireLength += pathDescription[i].length;
|
||||||
|
// lengthOfSegment += pathDescription[i].length;
|
||||||
|
// durationOfSegment += pathDescription[i].duration;
|
||||||
|
// pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||||
|
// pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||||
|
|
||||||
|
|
||||||
|
// if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
// //SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
|
||||||
|
// assert(pathDescription[i].necessary);
|
||||||
|
// lengthOfSegment = 0;
|
||||||
|
// durationOfSegment = 0;
|
||||||
|
// indexOfSegmentBegin = i;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||||
|
|
||||||
|
// //Post-processing to remove empty or nearly empty path segments
|
||||||
|
// if(FLT_EPSILON > pathDescription.back().length) {
|
||||||
|
// // SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
||||||
|
// if(pathDescription.size() > 2){
|
||||||
|
// pathDescription.pop_back();
|
||||||
|
// pathDescription.back().necessary = true;
|
||||||
|
// pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||||
|
// target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||||
|
// // SimpleLogger().Write() << "Deleting last turn instruction";
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||||
|
// }
|
||||||
|
// if(FLT_EPSILON > pathDescription[0].length) {
|
||||||
|
// //TODO: this is never called actually?
|
||||||
|
// if(pathDescription.size() > 2) {
|
||||||
|
// pathDescription.erase(pathDescription.begin());
|
||||||
|
// pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||||
|
// pathDescription[0].necessary = true;
|
||||||
|
// start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||||
|
// // SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// pathDescription[0].duration *= start_phantom.ratio;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //Generalize poly line
|
||||||
|
// dp.Run(pathDescription, zoomLevel);
|
||||||
|
|
||||||
|
// //fix what needs to be fixed else
|
||||||
|
// for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||||
|
// if(pathDescription[i].necessary) {
|
||||||
|
// double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||||
|
// pathDescription[i].bearing = angle;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // BuildRouteSummary(entireLength, duration);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void DescriptionFactory::BuildRouteSummary(
|
||||||
|
const double distance,
|
||||||
|
const unsigned time
|
||||||
|
) {
|
||||||
|
summary.startName = start_phantom.nodeBasedEdgeNameID;
|
||||||
|
summary.destName = target_phantom.nodeBasedEdgeNameID;
|
||||||
summary.BuildDurationAndLengthStrings(distance, time);
|
summary.BuildDurationAndLengthStrings(distance, time);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +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/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
@@ -44,20 +45,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
* and produces the description plus the encoded polyline */
|
* and produces the description plus the encoded polyline */
|
||||||
|
|
||||||
class DescriptionFactory {
|
class DescriptionFactory {
|
||||||
DouglasPeucker<SegmentInformation> dp;
|
DouglasPeucker polyline_generalizer;
|
||||||
PolylineCompressor pc;
|
PolylineCompressor polyline_compressor;
|
||||||
PhantomNode startPhantom, targetPhantom;
|
PhantomNode start_phantom, target_phantom;
|
||||||
|
|
||||||
double DegreeToRadian(const double degree) const;
|
double DegreeToRadian(const double degree) const;
|
||||||
double RadianToDegree(const double degree) const;
|
double RadianToDegree(const double degree) const;
|
||||||
public:
|
public:
|
||||||
struct _RouteSummary {
|
struct RouteSummary {
|
||||||
std::string lengthString;
|
std::string lengthString;
|
||||||
std::string durationString;
|
std::string durationString;
|
||||||
unsigned startName;
|
unsigned startName;
|
||||||
unsigned destName;
|
unsigned destName;
|
||||||
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
|
RouteSummary() :
|
||||||
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
|
lengthString("0"),
|
||||||
|
durationString("0"),
|
||||||
|
startName(0),
|
||||||
|
destName(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void BuildDurationAndLengthStrings(
|
||||||
|
const double distance,
|
||||||
|
const unsigned time
|
||||||
|
) {
|
||||||
//compute distance/duration for route summary
|
//compute distance/duration for route summary
|
||||||
intToString(round(distance), lengthString);
|
intToString(round(distance), lengthString);
|
||||||
int travelTime = time/10 + 1;
|
int travelTime = time/10 + 1;
|
||||||
@@ -72,14 +82,139 @@ public:
|
|||||||
DescriptionFactory();
|
DescriptionFactory();
|
||||||
virtual ~DescriptionFactory();
|
virtual ~DescriptionFactory();
|
||||||
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
||||||
void AppendEncodedPolylineString(std::string &output);
|
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
||||||
void AppendUnencodedPolylineString(std::string &output);
|
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||||
void AppendSegment(const 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 & startPhantom);
|
void SetStartSegment(const PhantomNode & start_phantom);
|
||||||
void SetEndSegment(const PhantomNode & startPhantom);
|
void SetEndSegment(const PhantomNode & start_phantom);
|
||||||
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
void AppendEncodedPolylineString(
|
||||||
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
|
const bool return_encoded,
|
||||||
|
std::vector<std::string> & output
|
||||||
|
);
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
void Run(const DataFacadeT * facade, const unsigned zoomLevel) {
|
||||||
|
|
||||||
|
if( pathDescription.empty() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsigned entireLength = 0;
|
||||||
|
/** starts at index 1 */
|
||||||
|
pathDescription[0].length = 0;
|
||||||
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||||
|
}
|
||||||
|
|
||||||
|
double lengthOfSegment = 0;
|
||||||
|
unsigned durationOfSegment = 0;
|
||||||
|
unsigned indexOfSegmentBegin = 0;
|
||||||
|
|
||||||
|
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].nameID);
|
||||||
|
// std::string string1;
|
||||||
|
|
||||||
|
|
||||||
|
/*Simplify turn instructions
|
||||||
|
Input :
|
||||||
|
10. Turn left on B 36 for 20 km
|
||||||
|
11. Continue on B 35; B 36 for 2 km
|
||||||
|
12. Continue on B 36 for 13 km
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
10. Turn left on B 36 for 35 km
|
||||||
|
*/
|
||||||
|
//TODO: rework to check only end and start of string.
|
||||||
|
// stl string is way to expensive
|
||||||
|
|
||||||
|
// unsigned lastTurn = 0;
|
||||||
|
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||||
|
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||||
|
// if(std::string::npos != string0.find(string1+";")
|
||||||
|
// || std::string::npos != string0.find(";"+string1)
|
||||||
|
// || std::string::npos != string0.find(string1+" ;")
|
||||||
|
// || std::string::npos != string0.find("; "+string1)
|
||||||
|
// ){
|
||||||
|
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||||
|
// for(; lastTurn != i; ++lastTurn)
|
||||||
|
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||||
|
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// } else if(std::string::npos != string1.find(string0+";")
|
||||||
|
// || std::string::npos != string1.find(";"+string0)
|
||||||
|
// || std::string::npos != string1.find(string0+" ;")
|
||||||
|
// || std::string::npos != string1.find("; "+string0)
|
||||||
|
// ){
|
||||||
|
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||||
|
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||||
|
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
// lastTurn = i;
|
||||||
|
// }
|
||||||
|
// string0 = string1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
entireLength += pathDescription[i].length;
|
||||||
|
lengthOfSegment += pathDescription[i].length;
|
||||||
|
durationOfSegment += pathDescription[i].duration;
|
||||||
|
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||||
|
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||||
|
|
||||||
|
|
||||||
|
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
|
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << pathDescription[i].nameID;
|
||||||
|
assert(pathDescription[i].necessary);
|
||||||
|
lengthOfSegment = 0;
|
||||||
|
durationOfSegment = 0;
|
||||||
|
indexOfSegmentBegin = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||||
|
|
||||||
|
//Post-processing to remove empty or nearly empty path segments
|
||||||
|
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
||||||
|
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
||||||
|
if(pathDescription.size() > 2){
|
||||||
|
pathDescription.pop_back();
|
||||||
|
pathDescription.back().necessary = true;
|
||||||
|
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||||
|
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||||
|
// SimpleLogger().Write() << "Deleting last turn instruction";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||||
|
}
|
||||||
|
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
||||||
|
//TODO: this is never called actually?
|
||||||
|
if(pathDescription.size() > 2) {
|
||||||
|
pathDescription.erase(pathDescription.begin());
|
||||||
|
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||||
|
pathDescription[0].necessary = true;
|
||||||
|
start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||||
|
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pathDescription[0].duration *= start_phantom.ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generalize poly line
|
||||||
|
polyline_generalizer.Run(pathDescription, zoomLevel);
|
||||||
|
|
||||||
|
//fix what needs to be fixed else
|
||||||
|
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||||
|
if(pathDescription[i].necessary) {
|
||||||
|
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||||
|
pathDescription[i].bearing = angle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildRouteSummary(entireLength, duration);
|
||||||
|
return;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DESCRIPTIONFACTORY_H_ */
|
#endif /* DESCRIPTIONFACTORY_H_ */
|
||||||
|
|||||||
+54
-24
@@ -32,42 +32,72 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
class GPXDescriptor : public BaseDescriptor{
|
template<class DataFacadeT>
|
||||||
|
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
public:
|
public:
|
||||||
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
|
||||||
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
//TODO: reorder parameters
|
||||||
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
void Run(
|
||||||
|
http::Reply & reply,
|
||||||
|
const RawRouteData &rawRoute,
|
||||||
|
PhantomNodes &phantomNodes,
|
||||||
|
const DataFacadeT * facade
|
||||||
|
) {
|
||||||
|
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
|
reply.content.push_back(
|
||||||
|
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||||
|
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||||
"\">";
|
"\">");
|
||||||
reply.content += "<metadata><copyright author=\"Project OSRM\"><license>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadata>";
|
reply.content.push_back(
|
||||||
reply.content += "<rte>";
|
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||||
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
|
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
"</metadata>");
|
||||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
reply.content.push_back("<rte>");
|
||||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) &&
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
(rawRoute.computedShortestPath.size() );
|
||||||
|
if( found_route ) {
|
||||||
|
convertInternalLatLonToString(
|
||||||
|
phantomNodes.startPhantom.location.lat,
|
||||||
|
tmp
|
||||||
|
);
|
||||||
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
|
convertInternalLatLonToString(
|
||||||
|
phantomNodes.startPhantom.location.lon,
|
||||||
|
tmp
|
||||||
|
);
|
||||||
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
|
|
||||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
BOOST_FOREACH(
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
const _PathData & pathData,
|
||||||
|
rawRoute.computedShortestPath
|
||||||
|
) {
|
||||||
|
current = facade->GetCoordinateOfNode(pathData.node);
|
||||||
|
|
||||||
convertInternalLatLonToString(current.lat, tmp);
|
convertInternalLatLonToString(current.lat, tmp);
|
||||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
convertInternalLatLonToString(current.lon, tmp);
|
convertInternalLatLonToString(current.lon, tmp);
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
}
|
}
|
||||||
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
|
convertInternalLatLonToString(
|
||||||
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
phantomNodes.targetPhantom.location.lat,
|
||||||
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
|
tmp
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
);
|
||||||
|
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||||
|
convertInternalLatLonToString(
|
||||||
|
phantomNodes.targetPhantom.location.lon,
|
||||||
|
tmp
|
||||||
|
);
|
||||||
|
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||||
}
|
}
|
||||||
reply.content += "</rte></gpx>";
|
reply.content.push_back("</rte></gpx>");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif /* GPX_DESCRIPTOR_H_ */
|
#endif // GPX_DESCRIPTOR_H_
|
||||||
|
|||||||
+279
-217
@@ -41,32 +41,33 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
class JSONDescriptor : public BaseDescriptor{
|
template<class DataFacadeT>
|
||||||
|
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
DescriptionFactory descriptionFactory;
|
DescriptionFactory description_factory;
|
||||||
DescriptionFactory alternateDescriptionFactory;
|
DescriptionFactory alternateDescriptionFactory;
|
||||||
FixedPointCoordinate current;
|
FixedPointCoordinate current;
|
||||||
unsigned numberOfEnteredRestrictedAreas;
|
unsigned entered_restricted_area_count;
|
||||||
struct RoundAbout{
|
struct RoundAbout{
|
||||||
RoundAbout() :
|
RoundAbout() :
|
||||||
startIndex(INT_MAX),
|
start_index(INT_MAX),
|
||||||
nameID(INT_MAX),
|
name_id(INT_MAX),
|
||||||
leaveAtExit(INT_MAX)
|
leave_at_exit(INT_MAX)
|
||||||
{}
|
{}
|
||||||
int startIndex;
|
int start_index;
|
||||||
int nameID;
|
int name_id;
|
||||||
int leaveAtExit;
|
int leave_at_exit;
|
||||||
} roundAbout;
|
} roundAbout;
|
||||||
|
|
||||||
struct Segment {
|
struct Segment {
|
||||||
Segment() : nameID(-1), length(-1), position(-1) {}
|
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||||
Segment(int n, int l, int p) : nameID(n), length(l), position(p) {}
|
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
||||||
int nameID;
|
int name_id;
|
||||||
int length;
|
int length;
|
||||||
int position;
|
int position;
|
||||||
};
|
};
|
||||||
std::vector<Segment> shortestSegments, alternativeSegments;
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||||
|
|
||||||
struct RouteNames {
|
struct RouteNames {
|
||||||
std::string shortestPathName1;
|
std::string shortestPathName1;
|
||||||
@@ -76,207 +77,246 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
JSONDescriptor() : entered_restricted_area_count(0) {}
|
||||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||||
|
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
//TODO: reorder parameters
|
||||||
|
void Run(
|
||||||
|
http::Reply & reply,
|
||||||
|
const RawRouteData & raw_route_information,
|
||||||
|
PhantomNodes & phantom_nodes,
|
||||||
|
const DataFacadeT * facade
|
||||||
|
) {
|
||||||
|
|
||||||
WriteHeaderToOutput(reply.content);
|
WriteHeaderToOutput(reply.content);
|
||||||
|
|
||||||
if(rawRoute.lengthOfShortestPath != INT_MAX) {
|
if(raw_route_information.lengthOfShortestPath != INT_MAX) {
|
||||||
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
description_factory.SetStartSegment(phantom_nodes.startPhantom);
|
||||||
reply.content += "0,"
|
reply.content.push_back("0,"
|
||||||
"\"status_message\": \"Found route between points\",";
|
"\"status_message\": \"Found route between points\",");
|
||||||
|
|
||||||
//Get all the coordinates for the computed route
|
//Get all the coordinates for the computed route
|
||||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedShortestPath) {
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
descriptionFactory.AppendSegment(current, pathData );
|
description_factory.AppendSegment(current, path_data );
|
||||||
}
|
}
|
||||||
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||||
} else {
|
} else {
|
||||||
//We do not need to do much, if there is no route ;-)
|
//We do not need to do much, if there is no route ;-)
|
||||||
reply.content += "207,"
|
reply.content.push_back("207,"
|
||||||
"\"status_message\": \"Cannot find route between points\",";
|
"\"status_message\": \"Cannot find route between points\",");
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptionFactory.Run(sEngine, config.z);
|
description_factory.Run(facade, config.zoom_level);
|
||||||
reply.content += "\"route_geometry\": ";
|
reply.content.push_back("\"route_geometry\": ");
|
||||||
if(config.geometry) {
|
if(config.geometry) {
|
||||||
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
description_factory.AppendEncodedPolylineString(
|
||||||
|
config.encode_geometry,
|
||||||
|
reply.content
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
reply.content += "[]";
|
reply.content.push_back("[]");
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"route_instructions\": [";
|
"\"route_instructions\": [");
|
||||||
numberOfEnteredRestrictedAreas = 0;
|
entered_restricted_area_count = 0;
|
||||||
if(config.instructions) {
|
if(config.instructions) {
|
||||||
BuildTextualDescription(descriptionFactory, reply, rawRoute.lengthOfShortestPath, sEngine, shortestSegments);
|
BuildTextualDescription(
|
||||||
|
description_factory,
|
||||||
|
reply,
|
||||||
|
raw_route_information.lengthOfShortestPath,
|
||||||
|
facade,
|
||||||
|
shortest_path_segments
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
BOOST_FOREACH(
|
||||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
const SegmentInformation & segment,
|
||||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
description_factory.pathDescription
|
||||||
|
) {
|
||||||
|
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||||
|
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, rawRoute.lengthOfShortestPath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
|
description_factory.BuildRouteSummary(
|
||||||
|
description_factory.entireLength,
|
||||||
|
raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty)
|
||||||
|
);
|
||||||
|
|
||||||
reply.content += "\"route_summary\":";
|
reply.content.push_back("\"route_summary\":");
|
||||||
reply.content += "{";
|
reply.content.push_back("{");
|
||||||
reply.content += "\"total_distance\":";
|
reply.content.push_back("\"total_distance\":");
|
||||||
reply.content += descriptionFactory.summary.lengthString;
|
reply.content.push_back(description_factory.summary.lengthString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"total_time\":";
|
"\"total_time\":");
|
||||||
reply.content += descriptionFactory.summary.durationString;
|
reply.content.push_back(description_factory.summary.durationString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"start_point\":\"";
|
"\"start_point\":\"");
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
|
reply.content.push_back(
|
||||||
reply.content += "\","
|
facade->GetEscapedNameForNameID(description_factory.summary.startName)
|
||||||
"\"end_point\":\"";
|
);
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
|
reply.content.push_back("\","
|
||||||
reply.content += "\"";
|
"\"end_point\":\"");
|
||||||
reply.content += "}";
|
reply.content.push_back(
|
||||||
reply.content +=",";
|
facade->GetEscapedNameForNameID(description_factory.summary.destName)
|
||||||
|
);
|
||||||
|
reply.content.push_back("\"");
|
||||||
|
reply.content.push_back("}");
|
||||||
|
reply.content.push_back(",");
|
||||||
|
|
||||||
//only one alternative route is computed at this time, so this is hardcoded
|
//only one alternative route is computed at this time, so this is hardcoded
|
||||||
|
|
||||||
if(rawRoute.lengthOfAlternativePath != INT_MAX) {
|
if(raw_route_information.lengthOfAlternativePath != INT_MAX) {
|
||||||
alternateDescriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
alternateDescriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
||||||
//Get all the coordinates for the computed route
|
//Get all the coordinates for the computed route
|
||||||
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedAlternativePath) {
|
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedAlternativePath) {
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
current = facade->GetCoordinateOfNode(path_data.node);
|
||||||
alternateDescriptionFactory.AppendSegment(current, pathData );
|
alternateDescriptionFactory.AppendSegment(current, path_data );
|
||||||
}
|
}
|
||||||
alternateDescriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
alternateDescriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||||
}
|
}
|
||||||
alternateDescriptionFactory.Run(sEngine, config.z);
|
alternateDescriptionFactory.Run(facade, config.zoom_level);
|
||||||
|
|
||||||
//give an array of alternative routes
|
//give an array of alternative routes
|
||||||
reply.content += "\"alternative_geometries\": [";
|
reply.content.push_back("\"alternative_geometries\": [");
|
||||||
if(config.geometry && INT_MAX != rawRoute.lengthOfAlternativePath) {
|
if(config.geometry && INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||||
//Generate the linestrings for each alternative
|
//Generate the linestrings for each alternative
|
||||||
alternateDescriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
alternateDescriptionFactory.AppendEncodedPolylineString(
|
||||||
|
config.encode_geometry,
|
||||||
|
reply.content
|
||||||
|
);
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"alternative_instructions\":[";
|
reply.content.push_back("\"alternative_instructions\":[");
|
||||||
numberOfEnteredRestrictedAreas = 0;
|
entered_restricted_area_count = 0;
|
||||||
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
|
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
//Generate instructions for each alternative
|
//Generate instructions for each alternative
|
||||||
if(config.instructions) {
|
if(config.instructions) {
|
||||||
BuildTextualDescription(alternateDescriptionFactory, reply, rawRoute.lengthOfAlternativePath, sEngine, alternativeSegments);
|
BuildTextualDescription(
|
||||||
|
alternateDescriptionFactory,
|
||||||
|
reply,
|
||||||
|
raw_route_information.lengthOfAlternativePath,
|
||||||
|
facade,
|
||||||
|
alternative_path_segments
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
||||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"alternative_summaries\":[";
|
reply.content.push_back("\"alternative_summaries\":[");
|
||||||
if(INT_MAX != rawRoute.lengthOfAlternativePath) {
|
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||||
//Generate route summary (length, duration) for each alternative
|
//Generate route summary (length, duration) for each alternative
|
||||||
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, rawRoute.lengthOfAlternativePath - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenalty));
|
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, raw_route_information.lengthOfAlternativePath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty));
|
||||||
reply.content += "{";
|
reply.content.push_back("{");
|
||||||
reply.content += "\"total_distance\":";
|
reply.content.push_back("\"total_distance\":");
|
||||||
reply.content += alternateDescriptionFactory.summary.lengthString;
|
reply.content.push_back(alternateDescriptionFactory.summary.lengthString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"total_time\":";
|
"\"total_time\":");
|
||||||
reply.content += alternateDescriptionFactory.summary.durationString;
|
reply.content.push_back(alternateDescriptionFactory.summary.durationString);
|
||||||
reply.content += ","
|
reply.content.push_back(","
|
||||||
"\"start_point\":\"";
|
"\"start_point\":\"");
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
|
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
||||||
reply.content += "\","
|
reply.content.push_back("\","
|
||||||
"\"end_point\":\"";
|
"\"end_point\":\"");
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
|
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += "}";
|
reply.content.push_back("}");
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
|
|
||||||
//Get Names for both routes
|
//Get Names for both routes
|
||||||
RouteNames routeNames;
|
RouteNames routeNames;
|
||||||
GetRouteNames(shortestSegments, alternativeSegments, sEngine, routeNames);
|
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
||||||
|
|
||||||
reply.content += "\"route_name\":[\"";
|
reply.content.push_back("\"route_name\":[\"");
|
||||||
reply.content += routeNames.shortestPathName1;
|
reply.content.push_back(routeNames.shortestPathName1);
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += routeNames.shortestPathName2;
|
reply.content.push_back(routeNames.shortestPathName2);
|
||||||
reply.content += "\"],"
|
reply.content.push_back("\"],"
|
||||||
"\"alternative_names\":[";
|
"\"alternative_names\":[");
|
||||||
reply.content += "[\"";
|
reply.content.push_back("[\"");
|
||||||
reply.content += routeNames.alternativePathName1;
|
reply.content.push_back(routeNames.alternativePathName1);
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += routeNames.alternativePathName2;
|
reply.content.push_back(routeNames.alternativePathName2);
|
||||||
reply.content += "\"]";
|
reply.content.push_back("\"]");
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
//list all viapoints so that the client may display it
|
//list all viapoints so that the client may display it
|
||||||
reply.content += "\"via_points\":[";
|
reply.content.push_back("\"via_points\":[");
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if(config.geometry && INT_MAX != rawRoute.lengthOfShortestPath) {
|
if(config.geometry && INT_MAX != raw_route_information.lengthOfShortestPath) {
|
||||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
if(rawRoute.segmentEndCoordinates[i].startPhantom.location.isSet())
|
if(raw_route_information.segmentEndCoordinates[i].startPhantom.location.isSet())
|
||||||
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[i].startPhantom.location, tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates[i].startPhantom.location, tmp);
|
||||||
else
|
else
|
||||||
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[i], tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates[i], tmp);
|
||||||
|
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
}
|
}
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
if(rawRoute.segmentEndCoordinates.back().startPhantom.location.isSet())
|
if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet())
|
||||||
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
||||||
else
|
else
|
||||||
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates.back(), tmp);
|
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp);
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"hint_data\": {";
|
reply.content.push_back("\"hint_data\": {");
|
||||||
reply.content += "\"checksum\":";
|
reply.content.push_back("\"checksum\":");
|
||||||
intToString(rawRoute.checkSum, tmp);
|
intToString(raw_route_information.checkSum, tmp);
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += ", \"locations\": [";
|
reply.content.push_back(", \"locations\": [");
|
||||||
|
|
||||||
std::string hint;
|
std::string hint;
|
||||||
for(unsigned i = 0; i < rawRoute.segmentEndCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
EncodeObjectToBase64(rawRoute.segmentEndCoordinates[i].startPhantom, hint);
|
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates[i].startPhantom, hint);
|
||||||
reply.content += hint;
|
reply.content.push_back(hint);
|
||||||
reply.content += "\", ";
|
reply.content.push_back("\", ");
|
||||||
}
|
}
|
||||||
EncodeObjectToBase64(rawRoute.segmentEndCoordinates.back().targetPhantom, hint);
|
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates.back().targetPhantom, hint);
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += hint;
|
reply.content.push_back(hint);
|
||||||
reply.content += "\"]";
|
reply.content.push_back("\"]");
|
||||||
reply.content += "},";
|
reply.content.push_back("},");
|
||||||
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
|
reply.content.push_back("\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"");
|
||||||
reply.content += "}";
|
reply.content.push_back("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
|
// construct routes names
|
||||||
/*** extract names for both alternatives ***/
|
void GetRouteNames(
|
||||||
|
std::vector<Segment> & shortest_path_segments,
|
||||||
|
std::vector<Segment> & alternative_path_segments,
|
||||||
|
const DataFacadeT * facade,
|
||||||
|
RouteNames & routeNames
|
||||||
|
) {
|
||||||
|
|
||||||
Segment shortestSegment1, shortestSegment2;
|
Segment shortestSegment1, shortestSegment2;
|
||||||
Segment alternativeSegment1, alternativeSegment2;
|
Segment alternativeSegment1, alternativeSegment2;
|
||||||
|
|
||||||
if(0 < shortestSegments.size()) {
|
if(0 < shortest_path_segments.size()) {
|
||||||
sort(shortestSegments.begin(), shortestSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
||||||
shortestSegment1 = shortestSegments[0];
|
shortestSegment1 = shortest_path_segments[0];
|
||||||
if(0 < alternativeSegments.size()) {
|
if(0 < alternative_path_segments.size()) {
|
||||||
sort(alternativeSegments.begin(), alternativeSegments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) );
|
||||||
alternativeSegment1 = alternativeSegments[0];
|
alternativeSegment1 = alternative_path_segments[0];
|
||||||
}
|
}
|
||||||
std::vector<Segment> shortestDifference(shortestSegments.size());
|
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
||||||
std::vector<Segment> alternativeDifference(alternativeSegments.size());
|
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
||||||
std::set_difference(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), alternative_path_segments.begin(), alternative_path_segments.end(), shortestDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
||||||
int size_of_difference = shortestDifference.size();
|
int size_of_difference = shortestDifference.size();
|
||||||
if(0 < size_of_difference ) {
|
if(0 < size_of_difference ) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
|
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(i < size_of_difference ) {
|
if(i < size_of_difference ) {
|
||||||
@@ -284,11 +324,11 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set_difference(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) );
|
||||||
size_of_difference = alternativeDifference.size();
|
size_of_difference = alternativeDifference.size();
|
||||||
if(0 < size_of_difference ) {
|
if(0 < size_of_difference ) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
|
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(i < size_of_difference ) {
|
if(i < size_of_difference ) {
|
||||||
@@ -301,102 +341,124 @@ public:
|
|||||||
if(alternativeSegment1.position > alternativeSegment2.position)
|
if(alternativeSegment1.position > alternativeSegment2.position)
|
||||||
std::swap(alternativeSegment1, alternativeSegment2);
|
std::swap(alternativeSegment1, alternativeSegment2);
|
||||||
|
|
||||||
routeNames.shortestPathName1 = sEngine.GetEscapedNameForNameID(shortestSegment1.nameID);
|
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID(
|
||||||
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
|
shortestSegment1.name_id
|
||||||
|
);
|
||||||
|
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID(
|
||||||
|
shortestSegment2.name_id
|
||||||
|
);
|
||||||
|
|
||||||
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
|
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID(
|
||||||
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
|
alternativeSegment1.name_id
|
||||||
|
);
|
||||||
|
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID(
|
||||||
|
alternativeSegment2.name_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void WriteHeaderToOutput(std::string & output) {
|
inline void WriteHeaderToOutput(std::vector<std::string> & output) {
|
||||||
output += "{"
|
output.push_back(
|
||||||
"\"version\": 0.3,"
|
"{"
|
||||||
"\"status\":";
|
"\"version\": 0.3,"
|
||||||
|
"\"status\":"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
|
//TODO: reorder parameters
|
||||||
|
inline void BuildTextualDescription(
|
||||||
|
DescriptionFactory & description_factory,
|
||||||
|
http::Reply & reply,
|
||||||
|
const int route_length,
|
||||||
|
const DataFacadeT * facade,
|
||||||
|
std::vector<Segment> & route_segments_list
|
||||||
|
) {
|
||||||
//Segment information has following format:
|
//Segment information has following format:
|
||||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||||
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
||||||
unsigned prefixSumOfNecessarySegments = 0;
|
unsigned prefixSumOfNecessarySegments = 0;
|
||||||
roundAbout.leaveAtExit = 0;
|
roundAbout.leave_at_exit = 0;
|
||||||
roundAbout.nameID = 0;
|
roundAbout.name_id = 0;
|
||||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
||||||
//Fetch data from Factory and generate a string from it.
|
//Fetch data from Factory and generate a string from it.
|
||||||
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
|
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
||||||
TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||||
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
|
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||||
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
|
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
|
||||||
if(TurnInstructions.EnterRoundAbout == currentInstruction) {
|
if(TurnInstructions.EnterRoundAbout == current_instruction) {
|
||||||
roundAbout.nameID = segment.nameID;
|
roundAbout.name_id = segment.nameID;
|
||||||
roundAbout.startIndex = prefixSumOfNecessarySegments;
|
roundAbout.start_index = prefixSumOfNecessarySegments;
|
||||||
} else {
|
} else {
|
||||||
if(0 != prefixSumOfNecessarySegments){
|
if(0 != prefixSumOfNecessarySegments){
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
}
|
}
|
||||||
reply.content += "[\"";
|
reply.content.push_back("[\"");
|
||||||
if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
|
if(TurnInstructions.LeaveRoundAbout == current_instruction) {
|
||||||
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
intToString(TurnInstructions.EnterRoundAbout, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
reply.content += "-";
|
reply.content.push_back("-");
|
||||||
intToString(roundAbout.leaveAtExit+1, tmpInstruction);
|
intToString(roundAbout.leave_at_exit+1, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
roundAbout.leaveAtExit = 0;
|
roundAbout.leave_at_exit = 0;
|
||||||
} else {
|
} else {
|
||||||
intToString(currentInstruction, tmpInstruction);
|
intToString(current_instruction, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reply.content.push_back("\",\"");
|
||||||
reply.content += "\",\"";
|
reply.content.push_back(facade->GetEscapedNameForNameID(segment.nameID));
|
||||||
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
|
reply.content.push_back("\",");
|
||||||
reply.content += "\",";
|
|
||||||
intToString(segment.length, tmpDist);
|
intToString(segment.length, tmpDist);
|
||||||
reply.content += tmpDist;
|
reply.content.push_back(tmpDist);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
intToString(prefixSumOfNecessarySegments, tmpLength);
|
intToString(prefixSumOfNecessarySegments, tmpLength);
|
||||||
reply.content += tmpLength;
|
reply.content.push_back(tmpLength);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
intToString(segment.duration/10, tmpDuration);
|
intToString(segment.duration/10, tmpDuration);
|
||||||
reply.content += tmpDuration;
|
reply.content.push_back(tmpDuration);
|
||||||
reply.content += ",\"";
|
reply.content.push_back(",\"");
|
||||||
intToString(segment.length, tmpLength);
|
intToString(segment.length, tmpLength);
|
||||||
reply.content += tmpLength;
|
reply.content.push_back(tmpLength);
|
||||||
reply.content += "m\",\"";
|
reply.content.push_back("m\",\"");
|
||||||
reply.content += Azimuth::Get(segment.bearing);
|
reply.content.push_back(Azimuth::Get(segment.bearing));
|
||||||
reply.content += "\",";
|
reply.content.push_back("\",");
|
||||||
intToString(round(segment.bearing), tmpBearing);
|
intToString(round(segment.bearing), tmpBearing);
|
||||||
reply.content += tmpBearing;
|
reply.content.push_back(tmpBearing);
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
|
|
||||||
segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() ));
|
route_segments_list.push_back(
|
||||||
|
Segment(
|
||||||
|
segment.nameID,
|
||||||
|
segment.length,
|
||||||
|
route_segments_list.size()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
|
} else if(TurnInstructions.StayOnRoundAbout == current_instruction) {
|
||||||
++roundAbout.leaveAtExit;
|
++roundAbout.leave_at_exit;
|
||||||
}
|
}
|
||||||
if(segment.necessary)
|
if(segment.necessary)
|
||||||
++prefixSumOfNecessarySegments;
|
++prefixSumOfNecessarySegments;
|
||||||
}
|
}
|
||||||
if(INT_MAX != lengthOfRoute) {
|
if(INT_MAX != route_length) {
|
||||||
reply.content += ",[\"";
|
reply.content.push_back(",[\"");
|
||||||
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
intToString(TurnInstructions.ReachedYourDestination, tmpInstruction);
|
||||||
reply.content += tmpInstruction;
|
reply.content.push_back(tmpInstruction);
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += "\",";
|
reply.content.push_back("\",");
|
||||||
reply.content += "0";
|
reply.content.push_back("0");
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
intToString(prefixSumOfNecessarySegments-1, tmpLength);
|
||||||
reply.content += tmpLength;
|
reply.content.push_back(tmpLength);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
reply.content += "0";
|
reply.content.push_back("0");
|
||||||
reply.content += ",\"";
|
reply.content.push_back(",\"");
|
||||||
reply.content += "\",\"";
|
reply.content.push_back("\",\"");
|
||||||
reply.content += Azimuth::Get(0.0);
|
reply.content.push_back(Azimuth::Get(0.0));
|
||||||
reply.content += "\",";
|
reply.content.push_back("\",");
|
||||||
reply.content += "0.0";
|
reply.content.push_back("0.0");
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+263
-159
@@ -27,266 +27,356 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include "ExtractionContainers.h"
|
||||||
|
|
||||||
void ExtractionContainers::PrepareData(const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM) {
|
void ExtractionContainers::PrepareData(
|
||||||
|
const std::string & output_file_name,
|
||||||
|
const std::string & restrictions_file_name
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
unsigned usedNodeCounter = 0;
|
unsigned number_of_used_nodes = 0;
|
||||||
unsigned usedEdgeCounter = 0;
|
unsigned number_of_used_edges = 0;
|
||||||
double time = get_timestamp();
|
double time = get_timestamp();
|
||||||
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
|
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||||
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
|
stxxl::sort(
|
||||||
|
used_node_id_list.begin(),
|
||||||
|
used_node_id_list.end(),
|
||||||
|
Cmp(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||||
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
|
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( used_node_id_list.begin(),used_node_id_list.end() ) ;
|
||||||
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
|
used_node_id_list.resize ( NewEnd - used_node_id_list.begin() );
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||||
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
all_nodes_list.begin(),
|
||||||
|
all_nodes_list.end(),
|
||||||
|
CmpNodeByID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||||
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
way_start_end_id_list.begin(),
|
||||||
|
way_start_end_id_list.end(),
|
||||||
|
CmpWayByID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
||||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
|
stxxl::sort(
|
||||||
|
restrictions_list.begin(),
|
||||||
|
restrictions_list.end(),
|
||||||
|
CmpRestrictionContainerByFrom(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||||
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
|
STXXLRestrictionsVector::iterator restrictions_iterator = restrictions_list.begin();
|
||||||
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
STXXLWayIDStartEndVector::iterator way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
|
|
||||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
while(
|
||||||
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->fromWay){
|
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
++wayStartAndEndEdgeIT;
|
restrictions_iterator != restrictions_list.end()
|
||||||
|
) {
|
||||||
|
|
||||||
|
if(way_start_and_end_iterator->wayID < restrictions_iterator->fromWay){
|
||||||
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->fromWay) {
|
|
||||||
++restrictionsIT;
|
if(way_start_and_end_iterator->wayID > restrictions_iterator->fromWay) {
|
||||||
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert(wayStartAndEndEdgeIT->wayID == restrictionsIT->fromWay);
|
|
||||||
NodeID viaNode = restrictionsIT->restriction.viaNode;
|
|
||||||
|
|
||||||
if(wayStartAndEndEdgeIT->firstStart == viaNode) {
|
BOOST_ASSERT(way_start_and_end_iterator->wayID == restrictions_iterator->fromWay);
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstTarget;
|
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
|
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->firstStart;
|
if(way_start_and_end_iterator->firstStart == via_node_id) {
|
||||||
} else if(wayStartAndEndEdgeIT->lastStart == viaNode) {
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstTarget;
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastTarget;
|
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
||||||
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->firstStart;
|
||||||
restrictionsIT->restriction.fromNode = wayStartAndEndEdgeIT->lastStart;
|
} else if(way_start_and_end_iterator->lastStart == via_node_id) {
|
||||||
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastTarget;
|
||||||
|
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
||||||
|
restrictions_iterator->restriction.fromNode = way_start_and_end_iterator->lastStart;
|
||||||
}
|
}
|
||||||
++restrictionsIT;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
||||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
|
stxxl::sort(
|
||||||
|
restrictions_list.begin(),
|
||||||
|
restrictions_list.end(),
|
||||||
|
CmpRestrictionContainerByTo(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
unsigned usableRestrictionsCounter(0);
|
unsigned usableRestrictionsCounter(0);
|
||||||
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||||
restrictionsIT = restrictionsVector.begin();
|
restrictions_iterator = restrictions_list.begin();
|
||||||
wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
way_start_and_end_iterator = way_start_end_id_list.begin();
|
||||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
while(
|
||||||
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
|
way_start_and_end_iterator != way_start_end_id_list.end() &&
|
||||||
++wayStartAndEndEdgeIT;
|
restrictions_iterator != restrictions_list.end()
|
||||||
|
) {
|
||||||
|
if(way_start_and_end_iterator->wayID < restrictions_iterator->toWay){
|
||||||
|
++way_start_and_end_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(wayStartAndEndEdgeIT->wayID > restrictionsIT->toWay) {
|
if(way_start_and_end_iterator->wayID > restrictions_iterator->toWay) {
|
||||||
++restrictionsIT;
|
++restrictions_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NodeID viaNode = restrictionsIT->restriction.viaNode;
|
NodeID via_node_id = restrictions_iterator->restriction.viaNode;
|
||||||
if(wayStartAndEndEdgeIT->lastStart == viaNode) {
|
if(way_start_and_end_iterator->lastStart == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastTarget;
|
||||||
} else if(wayStartAndEndEdgeIT->lastTarget == viaNode) {
|
} else if(way_start_and_end_iterator->lastTarget == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->lastStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->lastStart;
|
||||||
} else if(wayStartAndEndEdgeIT->firstStart == viaNode) {
|
} else if(way_start_and_end_iterator->firstStart == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstTarget;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstTarget;
|
||||||
} else if(wayStartAndEndEdgeIT->firstTarget == viaNode) {
|
} else if(way_start_and_end_iterator->firstTarget == via_node_id) {
|
||||||
restrictionsIT->restriction.toNode = wayStartAndEndEdgeIT->firstStart;
|
restrictions_iterator->restriction.toNode = way_start_and_end_iterator->firstStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
if(
|
||||||
UINT_MAX != restrictionsIT->restriction.fromNode &&
|
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
||||||
UINT_MAX != restrictionsIT->restriction.toNode
|
UINT_MAX != restrictions_iterator->restriction.toNode
|
||||||
) {
|
) {
|
||||||
++usableRestrictionsCounter;
|
++usableRestrictionsCounter;
|
||||||
}
|
}
|
||||||
++restrictionsIT;
|
++restrictions_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
||||||
//serialize restrictions
|
//serialize restrictions
|
||||||
std::ofstream restrictionsOutstream;
|
std::ofstream restrictions_out_stream;
|
||||||
restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
|
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||||
restrictionsOutstream.write((char*)&uuid, sizeof(UUID));
|
restrictions_out_stream.write((char*)&uuid, sizeof(UUID));
|
||||||
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
restrictions_out_stream.write(
|
||||||
|
(char*)&usableRestrictionsCounter,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
for(
|
for(
|
||||||
restrictionsIT = restrictionsVector.begin();
|
restrictions_iterator = restrictions_list.begin();
|
||||||
restrictionsIT != restrictionsVector.end();
|
restrictions_iterator != restrictions_list.end();
|
||||||
++restrictionsIT
|
++restrictions_iterator
|
||||||
) {
|
) {
|
||||||
if(
|
if(
|
||||||
UINT_MAX != restrictionsIT->restriction.fromNode &&
|
UINT_MAX != restrictions_iterator->restriction.fromNode &&
|
||||||
UINT_MAX != restrictionsIT->restriction.toNode
|
UINT_MAX != restrictions_iterator->restriction.toNode
|
||||||
) {
|
) {
|
||||||
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(TurnRestriction));
|
restrictions_out_stream.write(
|
||||||
|
(char *)&(restrictions_iterator->restriction),
|
||||||
|
sizeof(TurnRestriction)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restrictionsOutstream.close();
|
restrictions_out_stream.close();
|
||||||
|
|
||||||
std::ofstream fout;
|
std::ofstream file_out_stream;
|
||||||
fout.open(output_file_name.c_str(), std::ios::binary);
|
file_out_stream.open(output_file_name.c_str(), std::ios::binary);
|
||||||
fout.write((char*)&uuid, sizeof(UUID));
|
file_out_stream.write((char*)&uuid, sizeof(UUID));
|
||||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
||||||
|
|
||||||
STXXLNodeVector::iterator nodesIT = allNodes.begin();
|
//identify all used nodes by a merging step of two sorted lists
|
||||||
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
|
STXXLNodeVector::iterator node_iterator = all_nodes_list.begin();
|
||||||
while(usedNodeIDsIT != usedNodeIDs.end() && nodesIT != allNodes.end()) {
|
STXXLNodeIDVector::iterator node_id_iterator = used_node_id_list.begin();
|
||||||
if(*usedNodeIDsIT < nodesIT->id){
|
while(
|
||||||
++usedNodeIDsIT;
|
node_id_iterator != used_node_id_list.end() &&
|
||||||
|
node_iterator != all_nodes_list.end()
|
||||||
|
) {
|
||||||
|
if(*node_id_iterator < node_iterator->id){
|
||||||
|
++node_id_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*usedNodeIDsIT > nodesIT->id) {
|
if(*node_id_iterator > node_iterator->id) {
|
||||||
++nodesIT;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(*usedNodeIDsIT == nodesIT->id) {
|
BOOST_ASSERT( *node_id_iterator == node_iterator->id);
|
||||||
fout.write((char*)&(*nodesIT), sizeof(_Node));
|
|
||||||
++usedNodeCounter;
|
file_out_stream.write(
|
||||||
++usedNodeIDsIT;
|
(char*)&(*node_iterator),
|
||||||
++nodesIT;
|
sizeof(ExternalMemoryNode)
|
||||||
}
|
);
|
||||||
|
|
||||||
|
++number_of_used_nodes;
|
||||||
|
++node_id_iterator;
|
||||||
|
++node_iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
||||||
std::ios::pos_type positionInFile = fout.tellp();
|
std::ios::pos_type previous_file_position = file_out_stream.tellp();
|
||||||
fout.seekp(std::ios::beg+sizeof(UUID));
|
file_out_stream.seekp(std::ios::beg+sizeof(UUID));
|
||||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_nodes, sizeof(unsigned));
|
||||||
fout.seekp(positionInFile);
|
file_out_stream.seekp(previous_file_position);
|
||||||
|
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
// Sort edges by start.
|
// Sort edges by start.
|
||||||
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
all_edges_list.begin(),
|
||||||
|
all_edges_list.end(),
|
||||||
|
CmpEdgeByStartID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
||||||
// Traverse list of edges and nodes in parallel and set start coord
|
// Traverse list of edges and nodes in parallel and set start coord
|
||||||
nodesIT = allNodes.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
STXXLEdgeVector::iterator edgeIT = allEdges.begin();
|
STXXLEdgeVector::iterator edge_iterator = all_edges_list.begin();
|
||||||
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
|
while(
|
||||||
if(edgeIT->start < nodesIT->id){
|
edge_iterator != all_edges_list.end() &&
|
||||||
++edgeIT;
|
node_iterator != all_nodes_list.end()
|
||||||
|
) {
|
||||||
|
if(edge_iterator->start < node_iterator->id){
|
||||||
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->start > nodesIT->id) {
|
if(edge_iterator->start > node_iterator->id) {
|
||||||
nodesIT++;
|
node_iterator++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->start == nodesIT->id) {
|
|
||||||
edgeIT->startCoord.lat = nodesIT->lat;
|
BOOST_ASSERT(edge_iterator->start == node_iterator->id);
|
||||||
edgeIT->startCoord.lon = nodesIT->lon;
|
edge_iterator->startCoord.lat = node_iterator->lat;
|
||||||
++edgeIT;
|
edge_iterator->startCoord.lon = node_iterator->lon;
|
||||||
}
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
// Sort Edges by target
|
// Sort Edges by target
|
||||||
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
|
stxxl::sort(
|
||||||
|
all_edges_list.begin(),
|
||||||
|
all_edges_list.end(),
|
||||||
|
CmpEdgeByTargetID(),
|
||||||
|
4294967296
|
||||||
|
);
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
std::cout << "[extractor] Setting target coords ... " << std::flush;
|
||||||
// Traverse list of edges and nodes in parallel and set target coord
|
// Traverse list of edges and nodes in parallel and set target coord
|
||||||
nodesIT = allNodes.begin();
|
node_iterator = all_nodes_list.begin();
|
||||||
edgeIT = allEdges.begin();
|
edge_iterator = all_edges_list.begin();
|
||||||
|
|
||||||
while(edgeIT != allEdges.end() && nodesIT != allNodes.end()) {
|
while(
|
||||||
if(edgeIT->target < nodesIT->id){
|
edge_iterator != all_edges_list.end() &&
|
||||||
++edgeIT;
|
node_iterator != all_nodes_list.end()
|
||||||
|
) {
|
||||||
|
if(edge_iterator->target < node_iterator->id){
|
||||||
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->target > nodesIT->id) {
|
if(edge_iterator->target > node_iterator->id) {
|
||||||
++nodesIT;
|
++node_iterator;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(edgeIT->target == nodesIT->id) {
|
BOOST_ASSERT(edge_iterator->target == node_iterator->id);
|
||||||
if(edgeIT->startCoord.lat != INT_MIN && edgeIT->startCoord.lon != INT_MIN) {
|
if(edge_iterator->startCoord.lat != INT_MIN && edge_iterator->startCoord.lon != INT_MIN) {
|
||||||
edgeIT->targetCoord.lat = nodesIT->lat;
|
edge_iterator->targetCoord.lat = node_iterator->lat;
|
||||||
edgeIT->targetCoord.lon = nodesIT->lon;
|
edge_iterator->targetCoord.lon = node_iterator->lon;
|
||||||
|
|
||||||
double distance = ApproximateDistance(edgeIT->startCoord.lat, edgeIT->startCoord.lon, nodesIT->lat, nodesIT->lon);
|
const double distance = ApproximateDistance(
|
||||||
assert(edgeIT->speed != -1);
|
edge_iterator->startCoord.lat,
|
||||||
double weight = ( distance * 10. ) / (edgeIT->speed / 3.6);
|
edge_iterator->startCoord.lon,
|
||||||
int intWeight = std::max(1, (int)std::floor((edgeIT->isDurationSet ? edgeIT->speed : weight)+.5) );
|
node_iterator->lat,
|
||||||
int intDist = std::max(1, (int)distance);
|
node_iterator->lon
|
||||||
short zero = 0;
|
);
|
||||||
short one = 1;
|
|
||||||
|
|
||||||
fout.write((char*)&edgeIT->start, sizeof(unsigned));
|
BOOST_ASSERT(edge_iterator->speed != -1);
|
||||||
fout.write((char*)&edgeIT->target, sizeof(unsigned));
|
const double weight = ( distance * 10. ) / (edge_iterator->speed / 3.6);
|
||||||
fout.write((char*)&intDist, sizeof(int));
|
int integer_weight = std::max( 1, (int)std::floor((edge_iterator->isDurationSet ? edge_iterator->speed : weight)+.5) );
|
||||||
switch(edgeIT->direction) {
|
int integer_distance = std::max( 1, (int)distance );
|
||||||
case ExtractionWay::notSure:
|
short zero = 0;
|
||||||
fout.write((char*)&zero, sizeof(short));
|
short one = 1;
|
||||||
break;
|
|
||||||
case ExtractionWay::oneway:
|
|
||||||
fout.write((char*)&one, sizeof(short));
|
|
||||||
break;
|
|
||||||
case ExtractionWay::bidirectional:
|
|
||||||
fout.write((char*)&zero, sizeof(short));
|
|
||||||
|
|
||||||
break;
|
file_out_stream.write((char*)&edge_iterator->start, sizeof(unsigned));
|
||||||
case ExtractionWay::opposite:
|
file_out_stream.write((char*)&edge_iterator->target, sizeof(unsigned));
|
||||||
fout.write((char*)&one, sizeof(short));
|
file_out_stream.write((char*)&integer_distance, sizeof(int));
|
||||||
break;
|
switch(edge_iterator->direction) {
|
||||||
default:
|
case ExtractionWay::notSure:
|
||||||
std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
|
file_out_stream.write((char*)&zero, sizeof(short));
|
||||||
assert(false);
|
break;
|
||||||
break;
|
case ExtractionWay::oneway:
|
||||||
}
|
file_out_stream.write((char*)&one, sizeof(short));
|
||||||
fout.write((char*)&intWeight, sizeof(int));
|
break;
|
||||||
assert(edgeIT->type >= 0);
|
case ExtractionWay::bidirectional:
|
||||||
fout.write((char*)&edgeIT->type, sizeof(short));
|
file_out_stream.write((char*)&zero, sizeof(short));
|
||||||
fout.write((char*)&edgeIT->nameID, sizeof(unsigned));
|
|
||||||
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
|
break;
|
||||||
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
case ExtractionWay::opposite:
|
||||||
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
file_out_stream.write((char*)&one, sizeof(short));
|
||||||
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
|
break;
|
||||||
++usedEdgeCounter;
|
default:
|
||||||
|
throw OSRMException("edge has broken direction");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
++edgeIT;
|
file_out_stream.write(
|
||||||
|
(char*)&integer_weight, sizeof(int)
|
||||||
|
);
|
||||||
|
BOOST_ASSERT(edge_iterator->type >= 0);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->type,
|
||||||
|
sizeof(short)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->nameID,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->isRoundabout,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->ignoreInGrid,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->isAccessRestricted,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
file_out_stream.write(
|
||||||
|
(char*)&edge_iterator->isContraFlow,
|
||||||
|
sizeof(bool)
|
||||||
|
);
|
||||||
|
++number_of_used_edges;
|
||||||
}
|
}
|
||||||
|
++edge_iterator;
|
||||||
}
|
}
|
||||||
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||||
|
|
||||||
fout.seekp(positionInFile);
|
file_out_stream.seekp(previous_file_position);
|
||||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
file_out_stream.write((char*)&number_of_used_edges, sizeof(unsigned));
|
||||||
fout.close();
|
file_out_stream.close();
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
@@ -297,32 +387,46 @@ void ExtractionContainers::PrepareData(const std::string & output_file_name, con
|
|||||||
std::ios::binary
|
std::ios::binary
|
||||||
);
|
);
|
||||||
|
|
||||||
const unsigned number_of_ways = name_list.size()+1;
|
//write number of names
|
||||||
name_file_stream.write((char *)&(number_of_ways), sizeof(unsigned));
|
const unsigned number_of_names = name_list.size()+1;
|
||||||
|
name_file_stream.write((char *)&(number_of_names), sizeof(unsigned));
|
||||||
|
|
||||||
|
//compute total number of chars
|
||||||
|
unsigned total_number_of_chars = 0;
|
||||||
|
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||||
|
total_number_of_chars += temp_string.length();
|
||||||
|
}
|
||||||
|
//write total number of chars
|
||||||
|
name_file_stream.write(
|
||||||
|
(char *)&(total_number_of_chars),
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
//write prefixe sums
|
||||||
unsigned name_lengths_prefix_sum = 0;
|
unsigned name_lengths_prefix_sum = 0;
|
||||||
BOOST_FOREACH(const std::string & str, name_list) {
|
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||||
name_file_stream.write(
|
name_file_stream.write(
|
||||||
(char *)&(name_lengths_prefix_sum),
|
(char *)&(name_lengths_prefix_sum),
|
||||||
sizeof(unsigned)
|
sizeof(unsigned)
|
||||||
);
|
);
|
||||||
name_lengths_prefix_sum += strlen(str.c_str());
|
name_lengths_prefix_sum += temp_string.length();
|
||||||
}
|
}
|
||||||
|
//duplicate on purpose!
|
||||||
name_file_stream.write(
|
name_file_stream.write(
|
||||||
(char *)&(name_lengths_prefix_sum),
|
(char *)&(name_lengths_prefix_sum),
|
||||||
sizeof(unsigned)
|
sizeof(unsigned)
|
||||||
);
|
);
|
||||||
//duplicate on purpose!
|
|
||||||
name_file_stream.write((char *)&(name_lengths_prefix_sum), sizeof(unsigned));
|
//write all chars consecutively
|
||||||
BOOST_FOREACH(const std::string & str, name_list) {
|
BOOST_FOREACH(const std::string & temp_string, name_list) {
|
||||||
const unsigned lengthOfRawString = strlen(str.c_str());
|
const unsigned string_length = temp_string.length();
|
||||||
name_file_stream.write(str.c_str(), lengthOfRawString);
|
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;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() << "Processed " <<
|
||||||
"Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges";
|
number_of_used_nodes << " nodes and " <<
|
||||||
|
number_of_used_edges << " edges";
|
||||||
|
|
||||||
} catch ( const std::exception& e ) {
|
} catch ( const std::exception& e ) {
|
||||||
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
||||||
|
|||||||
@@ -33,48 +33,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
#include "../Util/UUID.h"
|
#include "../Util/UUID.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/foreach.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.h>
|
|
||||||
|
#include <stxxl/sort>
|
||||||
|
#include <stxxl/vector>
|
||||||
|
|
||||||
class ExtractionContainers {
|
class ExtractionContainers {
|
||||||
public:
|
public:
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||||
typedef stxxl::vector<_Node> STXXLNodeVector;
|
typedef stxxl::vector<ExternalMemoryNode> STXXLNodeVector;
|
||||||
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
typedef stxxl::vector<InternalExtractorEdge> STXXLEdgeVector;
|
||||||
typedef stxxl::vector<std::string> STXXLStringVector;
|
typedef stxxl::vector<std::string> STXXLStringVector;
|
||||||
typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector;
|
typedef stxxl::vector<InputRestrictionContainer> STXXLRestrictionsVector;
|
||||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||||
|
|
||||||
|
STXXLNodeIDVector used_node_id_list;
|
||||||
STXXLNodeIDVector usedNodeIDs;
|
STXXLNodeVector all_nodes_list;
|
||||||
STXXLNodeVector allNodes;
|
STXXLEdgeVector all_edges_list;
|
||||||
STXXLEdgeVector allEdges;
|
|
||||||
STXXLStringVector name_list;
|
STXXLStringVector name_list;
|
||||||
STXXLRestrictionsVector restrictionsVector;
|
STXXLRestrictionsVector restrictions_list;
|
||||||
STXXLWayIDStartEndVector wayStartEndVector;
|
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||||
const UUID uuid;
|
const UUID uuid;
|
||||||
|
|
||||||
ExtractionContainers() {
|
ExtractionContainers() {
|
||||||
//Check if another instance of stxxl is already running or if there is a general problem
|
//Check if stxxl can be instantiated
|
||||||
stxxl::vector<unsigned> testForRunningInstance;
|
stxxl::vector<unsigned> dummy_vector;
|
||||||
name_list.push_back("");
|
name_list.push_back("");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ExtractionContainers() {
|
virtual ~ExtractionContainers() {
|
||||||
usedNodeIDs.clear();
|
used_node_id_list.clear();
|
||||||
allNodes.clear();
|
all_nodes_list.clear();
|
||||||
allEdges.clear();
|
all_edges_list.clear();
|
||||||
name_list.clear();
|
name_list.clear();
|
||||||
restrictionsVector.clear();
|
restrictions_list.clear();
|
||||||
wayStartEndVector.clear();
|
way_start_end_id_list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareData(
|
void PrepareData(
|
||||||
const std::string & output_file_name,
|
const std::string & output_file_name,
|
||||||
const std::string restrictionsFileName,
|
const std::string & restrictions_file_name
|
||||||
const unsigned amountOfRAM
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * s
|
|||||||
ExtractorCallbacks::~ExtractorCallbacks() { }
|
ExtractorCallbacks::~ExtractorCallbacks() { }
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void ExtractorCallbacks::nodeFunction(const _Node &n) {
|
void ExtractorCallbacks::nodeFunction(const ExternalMemoryNode &n) {
|
||||||
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
||||||
externalMemory->allNodes.push_back(n);
|
externalMemory->all_nodes_list.push_back(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
|
bool ExtractorCallbacks::restrictionFunction(const InputRestrictionContainer &r) {
|
||||||
externalMemory->restrictionsVector.push_back(r);
|
externalMemory->restrictions_list.push_back(r);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||||
|
|
||||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->allEdges.push_back(
|
externalMemory->all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
parsed_way.path[n+1],
|
parsed_way.path[n+1],
|
||||||
parsed_way.type,
|
parsed_way.type,
|
||||||
@@ -99,17 +99,17 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
parsed_way.isAccessRestricted
|
parsed_way.isAccessRestricted
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
|
externalMemory->used_node_id_list.push_back(parsed_way.path[n]);
|
||||||
}
|
}
|
||||||
externalMemory->usedNodeIDs.push_back(parsed_way.path.back());
|
externalMemory->used_node_id_list.push_back(parsed_way.path.back());
|
||||||
|
|
||||||
//The following information is needed to identify start and end segments of restrictions
|
//The following information is needed to identify start and end segments of restrictions
|
||||||
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||||
|
|
||||||
if(split_bidirectional_edge) { //Only true if the way should be split
|
if(split_bidirectional_edge) { //Only true if the way should be split
|
||||||
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
||||||
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->allEdges.push_back(
|
externalMemory->all_edges_list.push_back(
|
||||||
InternalExtractorEdge(parsed_way.path[n],
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
parsed_way.path[n+1],
|
parsed_way.path[n+1],
|
||||||
parsed_way.type,
|
parsed_way.type,
|
||||||
@@ -124,7 +124,7 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
externalMemory->way_start_end_id_list.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ public:
|
|||||||
~ExtractorCallbacks();
|
~ExtractorCallbacks();
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void nodeFunction(const _Node &n);
|
void nodeFunction(const ExternalMemoryNode &n);
|
||||||
|
|
||||||
bool restrictionFunction(const _RawRestrictionContainer &r);
|
bool restrictionFunction(const InputRestrictionContainer &r);
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
void wayFunction(ExtractionWay &w);
|
void wayFunction(ExtractionWay &w);
|
||||||
|
|||||||
@@ -172,16 +172,19 @@ struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
|
struct CmpNodeByID : public std::binary_function<ExternalMemoryNode, ExternalMemoryNode, bool> {
|
||||||
typedef _Node value_type;
|
typedef ExternalMemoryNode value_type;
|
||||||
bool operator () (const _Node & a, const _Node & b) const {
|
bool operator () (
|
||||||
|
const ExternalMemoryNode & a,
|
||||||
|
const ExternalMemoryNode & b
|
||||||
|
) const {
|
||||||
return a.id < b.id;
|
return a.id < b.id;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() {
|
||||||
return _Node::max_value();
|
return ExternalMemoryNode::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
value_type min_value() {
|
||||||
return _Node::min_value();
|
return ExternalMemoryNode::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
|||||||
|
|
||||||
if(isRestriction) {
|
if(isRestriction) {
|
||||||
int64_t lastRef = 0;
|
int64_t lastRef = 0;
|
||||||
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
InputRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
||||||
for(
|
for(
|
||||||
int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
int rolesIndex = 0, last_role = inputRelation.roles_sid_size();
|
||||||
rolesIndex < last_role;
|
rolesIndex < last_role;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
.def_readwrite("lat", &ImportNode::lat)
|
.def_readwrite("lat", &ImportNode::lat)
|
||||||
.def_readwrite("lon", &ImportNode::lon)
|
.def_readwrite("lon", &ImportNode::lon)
|
||||||
.def_readwrite("id", &ImportNode::id)
|
.def_readonly("id", &ImportNode::id)
|
||||||
.def_readwrite("bollard", &ImportNode::bollard)
|
.def_readwrite("bollard", &ImportNode::bollard)
|
||||||
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
||||||
.def_readwrite("tags", &ImportNode::keyVals)
|
.def_readwrite("tags", &ImportNode::keyVals)
|
||||||
@@ -75,6 +75,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::class_<ExtractionWay>("Way")
|
luabind::class_<ExtractionWay>("Way")
|
||||||
.def(luabind::constructor<>())
|
.def(luabind::constructor<>())
|
||||||
|
.def_readonly("id", &ExtractionWay::id)
|
||||||
.def_readwrite("name", &ExtractionWay::name)
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
.def_readwrite("speed", &ExtractionWay::speed)
|
.def_readwrite("speed", &ExtractionWay::speed)
|
||||||
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||||
@@ -94,9 +95,11 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// fails on c++11/OS X 10.9
|
||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::class_<std::vector<std::string> >("vector")
|
luabind::class_<std::vector<std::string> >("vector")
|
||||||
.def("Add", &std::vector<std::string>::push_back)
|
.def("Add", static_cast<void (std::vector<std::string>::*)(const std::string&)>(&std::vector<std::string>::push_back)
|
||||||
|
)
|
||||||
];
|
];
|
||||||
|
|
||||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ bool XMLParser::Parse() {
|
|||||||
}
|
}
|
||||||
if( use_turn_restrictions ) {
|
if( use_turn_restrictions ) {
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||||
_RawRestrictionContainer r = _ReadXMLRestriction();
|
InputRestrictionContainer r = _ReadXMLRestriction();
|
||||||
if(r.fromWay != UINT_MAX) {
|
if(r.fromWay != UINT_MAX) {
|
||||||
if(!extractor_callbacks->restrictionFunction(r)) {
|
if(!extractor_callbacks->restrictionFunction(r)) {
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
@@ -87,8 +87,8 @@ bool XMLParser::Parse() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
InputRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||||
_RawRestrictionContainer restriction;
|
InputRestrictionContainer restriction;
|
||||||
std::string except_tag_string;
|
std::string except_tag_string;
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
bool Parse();
|
bool Parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_RawRestrictionContainer _ReadXMLRestriction();
|
InputRestrictionContainer _ReadXMLRestriction();
|
||||||
ExtractionWay _ReadXMLWay();
|
ExtractionWay _ReadXMLWay();
|
||||||
ImportNode _ReadXMLNode();
|
ImportNode _ReadXMLNode();
|
||||||
xmlTextReaderPtr inputReader;
|
xmlTextReaderPtr inputReader;
|
||||||
|
|||||||
+83
-16
@@ -26,39 +26,106 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "OSRM.h"
|
#include "OSRM.h"
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
|
OSRM::OSRM( const ServerPaths & server_paths, const bool use_shared_memory )
|
||||||
|
:
|
||||||
|
use_shared_memory(use_shared_memory)
|
||||||
|
{
|
||||||
|
if( !use_shared_memory ) {
|
||||||
|
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
|
||||||
|
server_paths
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
|
||||||
|
}
|
||||||
|
|
||||||
OSRM::OSRM(boost::unordered_map<const std::string,boost::filesystem::path>& paths) {
|
//The following plugins handle all requests.
|
||||||
objects = new QueryObjectsStorage( paths );
|
RegisterPlugin(
|
||||||
RegisterPlugin(new HelloWorldPlugin());
|
new HelloWorldPlugin()
|
||||||
RegisterPlugin(new LocatePlugin(objects));
|
);
|
||||||
RegisterPlugin(new NearestPlugin(objects));
|
RegisterPlugin(
|
||||||
RegisterPlugin(new TimestampPlugin(objects));
|
new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
RegisterPlugin(new ViaRoutePlugin(objects));
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new TimestampPlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
|
RegisterPlugin(
|
||||||
|
new ViaRoutePlugin<BaseDataFacade<QueryEdge::EdgeData> >(
|
||||||
|
query_data_facade
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
OSRM::~OSRM() {
|
OSRM::~OSRM() {
|
||||||
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, pluginMap) {
|
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
|
||||||
delete plugin_pointer.second;
|
delete plugin_pointer.second;
|
||||||
}
|
}
|
||||||
delete objects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
||||||
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||||
if( pluginMap.find(plugin->GetDescriptor()) != pluginMap.end() ) {
|
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
|
||||||
delete pluginMap.find(plugin->GetDescriptor())->second;
|
delete plugin_map.find(plugin->GetDescriptor())->second;
|
||||||
}
|
}
|
||||||
pluginMap.emplace(plugin->GetDescriptor(), plugin);
|
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||||
const PluginMap::const_iterator & iter = pluginMap.find(route_parameters.service);
|
const PluginMap::const_iterator & iter = plugin_map.find(
|
||||||
if(pluginMap.end() != iter) {
|
route_parameters.service
|
||||||
|
);
|
||||||
|
|
||||||
|
if(plugin_map.end() != iter) {
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
|
if( use_shared_memory ) {
|
||||||
|
// lock update pending
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> pending_lock(barrier.pending_update_mutex);
|
||||||
|
|
||||||
|
// lock query
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> query_lock(barrier.query_mutex);
|
||||||
|
|
||||||
|
// unlock update pending
|
||||||
|
pending_lock.unlock();
|
||||||
|
|
||||||
|
// increment query count
|
||||||
|
++(barrier.number_of_queries);
|
||||||
|
|
||||||
|
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
|
||||||
|
}
|
||||||
|
|
||||||
iter->second->HandleRequest(route_parameters, reply );
|
iter->second->HandleRequest(route_parameters, reply );
|
||||||
|
if( use_shared_memory ) {
|
||||||
|
// lock query
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> query_lock(barrier.query_mutex);
|
||||||
|
|
||||||
|
// decrement query count
|
||||||
|
--(barrier.number_of_queries);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 <= barrier.number_of_queries,
|
||||||
|
"invalid number of queries"
|
||||||
|
);
|
||||||
|
|
||||||
|
// notify all processes that were waiting for this condition
|
||||||
|
if (0 == barrier.number_of_queries) {
|
||||||
|
barrier.no_running_queries_condition.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-5
@@ -36,30 +36,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#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/InternalDataFacade.h"
|
||||||
|
#include "../Server/DataStructures/SharedBarriers.h"
|
||||||
|
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||||
#include "../Server/DataStructures/RouteParameters.h"
|
#include "../Server/DataStructures/RouteParameters.h"
|
||||||
#include "../Util/InputFileUtil.h"
|
#include "../Util/InputFileUtil.h"
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/ProgramOptions.h"
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Server/BasicDatastructures.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/interprocess/shared_memory_object.hpp>
|
||||||
|
#include <boost/interprocess/mapped_region.hpp>
|
||||||
|
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class OSRM : boost::noncopyable {
|
class OSRM : boost::noncopyable {
|
||||||
|
private:
|
||||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||||
QueryObjectsStorage * objects;
|
|
||||||
public:
|
public:
|
||||||
OSRM(boost::unordered_map<const std::string,boost::filesystem::path>& paths);
|
OSRM(
|
||||||
|
const ServerPaths & paths,
|
||||||
|
const bool use_shared_memory = false
|
||||||
|
);
|
||||||
~OSRM();
|
~OSRM();
|
||||||
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RegisterPlugin(BasePlugin * plugin);
|
void RegisterPlugin(BasePlugin * plugin);
|
||||||
PluginMap pluginMap;
|
PluginMap plugin_map;
|
||||||
|
bool use_shared_memory;
|
||||||
|
SharedBarriers barrier;
|
||||||
|
//base class pointer to the objects
|
||||||
|
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //OSRM_H
|
#endif //OSRM_H
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define BASEPLUGIN_H_
|
#define BASEPLUGIN_H_
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include "../Server/BasicDatastructures.h"
|
|
||||||
#include "../Server/DataStructures/RouteParameters.h"
|
#include "../Server/DataStructures/RouteParameters.h"
|
||||||
|
#include "../Server/Http/Reply.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
+50
-19
@@ -29,10 +29,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define HELLOWORLDPLUGIN_H_
|
#define HELLOWORLDPLUGIN_H_
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <string>
|
||||||
|
|
||||||
class HelloWorldPlugin : public BasePlugin {
|
class HelloWorldPlugin : public BasePlugin {
|
||||||
|
private:
|
||||||
|
std::string temp_string;
|
||||||
public:
|
public:
|
||||||
HelloWorldPlugin() : descriptor_string("hello"){}
|
HelloWorldPlugin() : descriptor_string("hello"){}
|
||||||
virtual ~HelloWorldPlugin() { }
|
virtual ~HelloWorldPlugin() { }
|
||||||
@@ -40,28 +43,56 @@ public:
|
|||||||
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
reply.content.push_back("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>");
|
||||||
std::stringstream content;
|
reply.content.push_back("<pre>");
|
||||||
content << "<pre>";
|
reply.content.push_back("zoom level: ");
|
||||||
content << "zoom level: " << routeParameters.zoomLevel << "\n";
|
intToString(routeParameters.zoomLevel, temp_string);
|
||||||
content << "checksum: " << routeParameters.checkSum << "\n";
|
reply.content.push_back(temp_string);
|
||||||
content << "instructions: " << (routeParameters.printInstructions ? "yes" : "no") << "\n";
|
reply.content.push_back("\nchecksum: ");
|
||||||
content << "geometry: " << (routeParameters.geometry ? "yes" : "no") << "\n";
|
intToString(routeParameters.checkSum, temp_string);
|
||||||
content << "compression: " << (routeParameters.compression ? "yes" : "no") << "\n";
|
reply.content.push_back(temp_string);
|
||||||
content << "output format: " << routeParameters.outputFormat << "\n";
|
reply.content.push_back("\ninstructions: ");
|
||||||
content << "json parameter: " << routeParameters.jsonpParameter << "\n";
|
reply.content.push_back((routeParameters.printInstructions ? "yes" : "no"));
|
||||||
content << "language: " << routeParameters.language << "<br>";
|
reply.content.push_back(temp_string);
|
||||||
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
|
reply.content.push_back("\ngeometry: ");
|
||||||
|
reply.content.push_back((routeParameters.geometry ? "yes" : "no"));
|
||||||
|
reply.content.push_back("\ncompression: ");
|
||||||
|
reply.content.push_back((routeParameters.compression ? "yes" : "no"));
|
||||||
|
reply.content.push_back("\noutput format: ");
|
||||||
|
reply.content.push_back(routeParameters.outputFormat);
|
||||||
|
reply.content.push_back("\njson parameter: ");
|
||||||
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
|
reply.content.push_back("\nlanguage: ");
|
||||||
|
reply.content.push_back(routeParameters.language);
|
||||||
|
reply.content.push_back("\nNumber of locations: ");
|
||||||
|
intToString(routeParameters.coordinates.size(), temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("\n");
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||||
content << " [" << i << "] " << routeParameters.coordinates[i].lat/COORDINATE_PRECISION << "," << routeParameters.coordinates[i].lon/COORDINATE_PRECISION << "\n";
|
reply.content.push_back( " [");
|
||||||
|
intToString(i, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("] ");
|
||||||
|
doubleToString(routeParameters.coordinates[i].lat/COORDINATE_PRECISION, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back(",");
|
||||||
|
doubleToString(routeParameters.coordinates[i].lon/COORDINATE_PRECISION, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("\n");
|
||||||
}
|
}
|
||||||
content << "Number of hints: " << routeParameters.hints.size() << "\n";
|
reply.content.push_back( "Number of hints: ");
|
||||||
|
intToString(routeParameters.hints.size(), temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("\n");
|
||||||
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
||||||
content << " [" << i << "] " << routeParameters.hints[i] << "\n";
|
reply.content.push_back( " [");
|
||||||
|
intToString(i, temp_string);
|
||||||
|
reply.content.push_back(temp_string);
|
||||||
|
reply.content.push_back("] ");
|
||||||
|
reply.content.push_back(routeParameters.hints[i]);
|
||||||
|
reply.content.push_back("\n");
|
||||||
}
|
}
|
||||||
content << "</pre>";
|
reply.content.push_back( "</pre></body></html>");
|
||||||
reply.content.append(content.str());
|
|
||||||
reply.content.append("</body></html>");
|
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
|
|||||||
+45
-33
@@ -29,27 +29,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define LOCATEPLUGIN_H_
|
#define LOCATEPLUGIN_H_
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
/*
|
//locates the nearest node in the road network for a given coordinate.
|
||||||
* This Plugin locates the nearest node in the road network for a given coordinate.
|
|
||||||
*/
|
template<class DataFacadeT>
|
||||||
class LocatePlugin : public BasePlugin {
|
class LocatePlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
LocatePlugin(QueryObjectsStorage * objects) : descriptor_string("locate") {
|
LocatePlugin(DataFacadeT * facade)
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
:
|
||||||
}
|
descriptor_string("locate"),
|
||||||
|
facade(facade)
|
||||||
|
{ }
|
||||||
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
|
||||||
|
) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
if(false == checkCoord(routeParameters.coordinates[0])) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,35 +62,39 @@ public:
|
|||||||
std::string tmp;
|
std::string tmp;
|
||||||
//json
|
//json
|
||||||
|
|
||||||
// JSONParameter = routeParameters.options.Find("jsonp");
|
if(!routeParameters.jsonpParameter.empty()) {
|
||||||
if("" != routeParameters.jsonpParameter) {
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back("(");
|
||||||
reply.content += "(";
|
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("{");
|
reply.content.push_back ("{");
|
||||||
reply.content += ("\"version\":0.3,");
|
reply.content.push_back ("\"version\":0.3,");
|
||||||
if(!nodeHelpDesk->LocateClosestEndPointForCoordinate(routeParameters.coordinates[0], result)) {
|
if(
|
||||||
reply.content += ("\"status\":207,");
|
!facade->LocateClosestEndPointForCoordinate(
|
||||||
reply.content += ("\"mapped_coordinate\":[]");
|
routeParameters.coordinates[0],
|
||||||
|
result
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
reply.content.push_back ("\"status\":207,");
|
||||||
|
reply.content.push_back ("\"mapped_coordinate\":[]");
|
||||||
} else {
|
} else {
|
||||||
//Write coordinate to stream
|
//Write coordinate to stream
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("\"status\":0,");
|
reply.content.push_back ("\"status\":0,");
|
||||||
reply.content += ("\"mapped_coordinate\":");
|
reply.content.push_back ("\"mapped_coordinate\":");
|
||||||
convertInternalLatLonToString(result.lat, tmp);
|
convertInternalLatLonToString(result.lat, tmp);
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
convertInternalLatLonToString(result.lon, tmp);
|
convertInternalLatLonToString(result.lon, tmp);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
reply.content += tmp;
|
reply.content.push_back(tmp);
|
||||||
reply.content += "]";
|
reply.content.push_back("]");
|
||||||
}
|
}
|
||||||
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
|
reply.content.push_back(",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"");
|
||||||
reply.content += ("}");
|
reply.content.push_back("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if(!routeParameters.jsonpParameter.empty()) {
|
||||||
reply.content += ")";
|
reply.content.push_back( ")");
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -98,14 +106,18 @@ public:
|
|||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||||
}
|
}
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
intToString(reply.content.size(), tmp);
|
unsigned content_length = 0;
|
||||||
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
|
}
|
||||||
|
intToString(content_length, tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
|
DataFacadeT * facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LOCATEPLUGIN_H_ */
|
#endif /* LOCATEPLUGIN_H_ */
|
||||||
|
|||||||
+37
-34
@@ -29,19 +29,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define NearestPlugin_H_
|
#define NearestPlugin_H_
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class NearestPlugin : public BasePlugin {
|
class NearestPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
NearestPlugin(QueryObjectsStorage * objects )
|
NearestPlugin(DataFacadeT * facade )
|
||||||
:
|
:
|
||||||
m_query_objects(objects),
|
facade(facade),
|
||||||
descriptor_string("nearest")
|
descriptor_string("nearest")
|
||||||
{
|
{
|
||||||
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
||||||
@@ -51,17 +51,16 @@ public:
|
|||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(false == checkCoord(routeParameters.coordinates[0])) {
|
if( !checkCoord(routeParameters.coordinates[0]) ) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
NodeInformationHelpDesk * nodeHelpDesk = m_query_objects->nodeHelpDesk;
|
|
||||||
//query to helpdesk
|
|
||||||
PhantomNode result;
|
PhantomNode result;
|
||||||
nodeHelpDesk->FindPhantomNodeForCoordinate(
|
facade->FindPhantomNodeForCoordinate(
|
||||||
routeParameters.coordinates[0],
|
routeParameters.coordinates[0],
|
||||||
result,
|
result,
|
||||||
routeParameters.zoomLevel
|
routeParameters.zoomLevel
|
||||||
@@ -71,40 +70,40 @@ public:
|
|||||||
//json
|
//json
|
||||||
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += "(";
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("{");
|
reply.content.push_back("{");
|
||||||
reply.content += ("\"version\":0.3,");
|
reply.content.push_back("\"version\":0.3,");
|
||||||
reply.content += ("\"status\":");
|
reply.content.push_back("\"status\":");
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
if(UINT_MAX != result.edgeBasedNode) {
|
||||||
reply.content += "0,";
|
reply.content.push_back("0,");
|
||||||
} else {
|
} else {
|
||||||
reply.content += "207,";
|
reply.content.push_back("207,");
|
||||||
}
|
}
|
||||||
reply.content += ("\"mapped_coordinate\":");
|
reply.content.push_back("\"mapped_coordinate\":");
|
||||||
reply.content += "[";
|
reply.content.push_back("[");
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
if(UINT_MAX != result.edgeBasedNode) {
|
||||||
convertInternalLatLonToString(result.location.lat, temp_string);
|
convertInternalLatLonToString(result.location.lat, temp_string);
|
||||||
reply.content += temp_string;
|
reply.content.push_back(temp_string);
|
||||||
convertInternalLatLonToString(result.location.lon, temp_string);
|
convertInternalLatLonToString(result.location.lon, temp_string);
|
||||||
reply.content += ",";
|
reply.content.push_back(",");
|
||||||
reply.content += temp_string;
|
reply.content.push_back(temp_string);
|
||||||
}
|
}
|
||||||
reply.content += "],";
|
reply.content.push_back("],");
|
||||||
reply.content += "\"name\":\"";
|
reply.content.push_back("\"name\":\"");
|
||||||
if(UINT_MAX != result.edgeBasedNode) {
|
if(UINT_MAX != result.edgeBasedNode) {
|
||||||
m_query_objects->GetName(result.nodeBasedEdgeNameID, temp_string);
|
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
|
||||||
reply.content += temp_string;
|
reply.content.push_back(temp_string);
|
||||||
}
|
}
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
|
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"");
|
||||||
reply.content += ("}");
|
reply.content.push_back("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if( !routeParameters.jsonpParameter.empty() ) {
|
||||||
reply.content += ")";
|
reply.content.push_back(")");
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -116,12 +115,16 @@ public:
|
|||||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||||
}
|
}
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
intToString(reply.content.size(), temp_string);
|
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;
|
reply.headers[0].value = temp_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QueryObjectsStorage * m_query_objects;
|
DataFacadeT * facade;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
HashTable<std::string, unsigned> descriptorTable;
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|||||||
+21
-17
@@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class TimestampPlugin : public BasePlugin {
|
class TimestampPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
TimestampPlugin(QueryObjectsStorage * o)
|
TimestampPlugin(const DataFacadeT * facade)
|
||||||
: objects(o), descriptor_string("timestamp")
|
: facade(facade), descriptor_string("timestamp")
|
||||||
{ }
|
{ }
|
||||||
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) {
|
||||||
@@ -41,23 +42,23 @@ public:
|
|||||||
|
|
||||||
//json
|
//json
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += "(";
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
reply.content += ("{");
|
reply.content.push_back("{");
|
||||||
reply.content += ("\"version\":0.3,");
|
reply.content.push_back("\"version\":0.3,");
|
||||||
reply.content += ("\"status\":");
|
reply.content.push_back("\"status\":");
|
||||||
reply.content += "0,";
|
reply.content.push_back("0,");
|
||||||
reply.content += ("\"timestamp\":\"");
|
reply.content.push_back("\"timestamp\":\"");
|
||||||
reply.content += objects->timestamp;
|
reply.content.push_back(facade->GetTimestamp());
|
||||||
reply.content += "\"";
|
reply.content.push_back("\"");
|
||||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"";
|
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"");
|
||||||
reply.content += ("}");
|
reply.content.push_back("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")";
|
reply.content.push_back(")");
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -68,12 +69,15 @@ public:
|
|||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
||||||
}
|
}
|
||||||
reply.headers[0].name = "Content-Length";
|
unsigned content_length = 0;
|
||||||
intToString(reply.content.size(), tmp);
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
|
}
|
||||||
|
intToString(content_length, tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
QueryObjectsStorage * objects;
|
const DataFacadeT * facade;
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+56
-46
@@ -32,12 +32,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/StaticGraph.h"
|
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
#include "../Descriptors/GPXDescriptor.h"
|
#include "../Descriptors/GPXDescriptor.h"
|
||||||
#include "../Descriptors/JSONDescriptor.h"
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
@@ -48,49 +46,48 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
class ViaRoutePlugin : public BasePlugin {
|
class ViaRoutePlugin : public BasePlugin {
|
||||||
private:
|
private:
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||||
StaticGraph<QueryEdge::EdgeData> * graph;
|
SearchEngine<DataFacadeT> * search_engine_ptr;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
|
||||||
SearchEngine * searchEnginePtr;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ViaRoutePlugin(QueryObjectsStorage * objects)
|
ViaRoutePlugin(DataFacadeT * facade)
|
||||||
:
|
:
|
||||||
// objects(objects),
|
descriptor_string("viaroute"),
|
||||||
descriptor_string("viaroute")
|
facade(facade)
|
||||||
{
|
{
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
//TODO: set up an engine for each thread!!
|
||||||
graph = objects->graph;
|
search_engine_ptr = new SearchEngine<DataFacadeT>(facade);
|
||||||
|
|
||||||
searchEnginePtr = new SearchEngine(objects);
|
|
||||||
|
|
||||||
// descriptorTable.emplace("" , 0);
|
|
||||||
descriptorTable.emplace("json", 0);
|
descriptorTable.emplace("json", 0);
|
||||||
descriptorTable.emplace("gpx" , 1);
|
descriptorTable.emplace("gpx" , 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() {
|
||||||
delete searchEnginePtr;
|
delete search_engine_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if( 2 > routeParameters.coordinates.size() ) {
|
if( 2 > routeParameters.coordinates.size() ) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawRouteData rawRoute;
|
RawRouteData rawRoute;
|
||||||
rawRoute.checkSum = nodeHelpDesk->GetCheckSum();
|
rawRoute.checkSum = facade->GetCheckSum();
|
||||||
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
||||||
std::vector<std::string> textCoord;
|
std::vector<std::string> textCoord;
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||||
if(false == checkCoord(routeParameters.coordinates[i])) {
|
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
||||||
reply = http::Reply::stockReply(http::Reply::badRequest);
|
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]);
|
||||||
@@ -100,13 +97,17 @@ public:
|
|||||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
||||||
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
||||||
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
||||||
if(phantomNodeVector[i].isValid(nodeHelpDesk->GetNumberOfNodes())) {
|
if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) {
|
||||||
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
||||||
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
|
facade->FindPhantomNodeForCoordinate(
|
||||||
|
rawRoute.rawViaNodeCoordinates[i],
|
||||||
|
phantomNodeVector[i],
|
||||||
|
routeParameters.zoomLevel
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||||
@@ -115,73 +116,81 @@ public:
|
|||||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||||
}
|
}
|
||||||
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
if(
|
||||||
// SimpleLogger().Write() << "Checking for alternative paths";
|
( routeParameters.alternateRoute ) &&
|
||||||
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
(1 == rawRoute.segmentEndCoordinates.size())
|
||||||
|
) {
|
||||||
|
search_engine_ptr->alternative_path(
|
||||||
|
rawRoute.segmentEndCoordinates[0],
|
||||||
|
rawRoute
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
search_engine_ptr->shortest_path(
|
||||||
|
rawRoute.segmentEndCoordinates,
|
||||||
|
rawRoute
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
||||||
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;
|
||||||
|
|
||||||
//TODO: Move to member as smart pointer
|
//TODO: Move to member as smart pointer
|
||||||
BaseDescriptor * desc;
|
BaseDescriptor<DataFacadeT> * desc;
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content.push_back(routeParameters.jsonpParameter);
|
||||||
reply.content += "(";
|
reply.content.push_back("(");
|
||||||
}
|
}
|
||||||
|
|
||||||
_DescriptorConfig descriptorConfig;
|
DescriptorConfig descriptorConfig;
|
||||||
|
|
||||||
unsigned descriptorType = 0;
|
unsigned descriptorType = 0;
|
||||||
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
if(descriptorTable.find(routeParameters.outputFormat) != descriptorTable.end() ) {
|
||||||
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
|
descriptorType = descriptorTable.find(routeParameters.outputFormat)->second;
|
||||||
}
|
}
|
||||||
descriptorConfig.z = routeParameters.zoomLevel;
|
descriptorConfig.zoom_level = routeParameters.zoomLevel;
|
||||||
descriptorConfig.instructions = routeParameters.printInstructions;
|
descriptorConfig.instructions = routeParameters.printInstructions;
|
||||||
descriptorConfig.geometry = routeParameters.geometry;
|
descriptorConfig.geometry = routeParameters.geometry;
|
||||||
descriptorConfig.encodeGeometry = routeParameters.compression;
|
descriptorConfig.encode_geometry = routeParameters.compression;
|
||||||
|
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
case 0:
|
||||||
desc = new JSONDescriptor();
|
desc = new JSONDescriptor<DataFacadeT>();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
desc = new GPXDescriptor();
|
desc = new GPXDescriptor<DataFacadeT>();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
desc = new JSONDescriptor();
|
desc = new JSONDescriptor<DataFacadeT>();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes phantomNodes;
|
PhantomNodes phantomNodes;
|
||||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
||||||
// SimpleLogger().Write() << "Start location: " << phantomNodes.startPhantom.location;
|
|
||||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
||||||
// SimpleLogger().Write() << "TargetLocation: " << phantomNodes.targetPhantom.location;
|
|
||||||
// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size();
|
|
||||||
desc->SetConfig(descriptorConfig);
|
desc->SetConfig(descriptorConfig);
|
||||||
|
|
||||||
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
|
desc->Run(reply, rawRoute, phantomNodes, facade);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")\n";
|
reply.content.push_back(")\n");
|
||||||
}
|
}
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
reply.headers[0].name = "Content-Length";
|
reply.headers[0].name = "Content-Length";
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
intToString(reply.content.size(), tmp);
|
unsigned content_length = 0;
|
||||||
|
BOOST_FOREACH(const std::string & snippet, reply.content) {
|
||||||
|
content_length += snippet.length();
|
||||||
|
}
|
||||||
|
intToString(content_length, tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
case 0:
|
||||||
if("" != routeParameters.jsonpParameter){
|
if( !routeParameters.jsonpParameter.empty() ){
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -202,7 +211,7 @@ public:
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if("" != routeParameters.jsonpParameter){
|
if( !routeParameters.jsonpParameter.empty() ){
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@@ -221,6 +230,7 @@ public:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
|
DataFacadeT * facade;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ require 'sys/proctable'
|
|||||||
|
|
||||||
BUILD_FOLDER = 'build'
|
BUILD_FOLDER = 'build'
|
||||||
DATA_FOLDER = 'sandbox'
|
DATA_FOLDER = 'sandbox'
|
||||||
PROFILE = 'bicycle'
|
PROFILE = 'examples/postgis'
|
||||||
OSRM_PORT = 5000
|
OSRM_PORT = 5000
|
||||||
PROFILES_FOLDER = '../profiles'
|
PROFILES_FOLDER = '../profiles'
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define ALTERNATIVEROUTES_H_
|
#define ALTERNATIVEROUTES_H_
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -37,15 +39,20 @@ const double VIAPATH_ALPHA = 0.15;
|
|||||||
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
|
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
|
||||||
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
|
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
|
||||||
|
|
||||||
template<class QueryDataT>
|
template<class DataFacadeT>
|
||||||
class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
|
class AlternativeRouting : private BasicRoutingInterface<DataFacadeT> {
|
||||||
typedef BasicRoutingInterface<QueryDataT> super;
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||||
typedef typename QueryDataT::Graph SearchGraph;
|
typedef typename DataFacadeT::EdgeData EdgeData;
|
||||||
typedef typename QueryDataT::QueryHeap QueryHeap;
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||||
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
|
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
|
||||||
|
|
||||||
struct RankedCandidateNode {
|
struct RankedCandidateNode {
|
||||||
RankedCandidateNode(const NodeID n, const int l, const int s) : node(n), length(l), sharing(s) {}
|
RankedCandidateNode(const NodeID n, const int l, const int s) :
|
||||||
|
node(n),
|
||||||
|
length(l),
|
||||||
|
sharing(s)
|
||||||
|
{ }
|
||||||
|
|
||||||
NodeID node;
|
NodeID node;
|
||||||
int length;
|
int length;
|
||||||
int sharing;
|
int sharing;
|
||||||
@@ -53,66 +60,129 @@ class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
|
|||||||
return (2*length + sharing) < (2*other.length + other.sharing);
|
return (2*length + sharing) < (2*other.length + other.sharing);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
DataFacadeT * facade;
|
||||||
const SearchGraph * search_graph;
|
SearchEngineData & engine_working_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
|
AlternativeRouting(
|
||||||
|
DataFacadeT * facade,
|
||||||
|
SearchEngineData & engine_working_data
|
||||||
|
) :
|
||||||
|
super(facade),
|
||||||
|
facade(facade),
|
||||||
|
engine_working_data(engine_working_data)
|
||||||
|
{ }
|
||||||
|
|
||||||
~AlternativeRouting() {}
|
~AlternativeRouting() {}
|
||||||
|
|
||||||
void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) {
|
void operator()(
|
||||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) {
|
const PhantomNodes & phantom_node_pair,
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
RawRouteData & raw_route_data) {
|
||||||
|
if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) ||
|
||||||
|
phantom_node_pair.PhantomNodesHaveEqualLocation()
|
||||||
|
) {
|
||||||
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NodeID> alternativePath;
|
std::vector<NodeID> alternative_path;
|
||||||
std::vector<NodeID> viaNodeCandidates;
|
std::vector<NodeID> via_node_candidate_list;
|
||||||
std::vector<SearchSpaceEdge> forward_search_space;
|
std::vector<SearchSpaceEdge> forward_search_space;
|
||||||
std::vector<SearchSpaceEdge> reverse_search_space;
|
std::vector<SearchSpaceEdge> reverse_search_space;
|
||||||
|
|
||||||
//Initialize Queues, semi-expensive because access to TSS invokes a system call
|
//Init queues, semi-expensive because access to TSS invokes a sys-call
|
||||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
super::facade->GetNumberOfNodes()
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
);
|
||||||
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
|
||||||
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
|
||||||
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
||||||
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
||||||
|
|
||||||
int upper_bound_to_shortest_path_distance = INT_MAX;
|
int upper_bound_to_shortest_path_distance = INT_MAX;
|
||||||
NodeID middle_node = UINT_MAX;
|
NodeID middle_node = UINT_MAX;
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap1.Insert(
|
||||||
if(phantomNodePair.startPhantom.isBidirected() ) {
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
-phantom_node_pair.startPhantom.weight1,
|
||||||
}
|
phantom_node_pair.startPhantom.edgeBasedNode
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
);
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
if(phantom_node_pair.startPhantom.isBidirected() ) {
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||||
|
-phantom_node_pair.startPhantom.weight2,
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
reverse_heap1.Insert(
|
||||||
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
phantom_node_pair.targetPhantom.edgeBasedNode,
|
||||||
|
phantom_node_pair.targetPhantom.weight1,
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode
|
||||||
|
);
|
||||||
|
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
||||||
|
reverse_heap1.Insert(
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
||||||
|
phantom_node_pair.targetPhantom.weight2,
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
const int forward_offset = super::ComputeEdgeOffset(
|
||||||
|
phantom_node_pair.startPhantom
|
||||||
|
);
|
||||||
|
const int reverse_offset = super::ComputeEdgeOffset(
|
||||||
|
phantom_node_pair.targetPhantom
|
||||||
|
);
|
||||||
|
|
||||||
|
//search from s and t till new_min/(1+epsilon) > length_of_shortest_path
|
||||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
|
||||||
if(0 < forward_heap1.Size()){
|
if(0 < forward_heap1.Size()){
|
||||||
AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
|
AlternativeRoutingStep<true>(
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
&middle_node,
|
||||||
|
&upper_bound_to_shortest_path_distance,
|
||||||
|
via_node_candidate_list,
|
||||||
|
forward_search_space,
|
||||||
|
forward_offset
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap1.Size()){
|
if(0 < reverse_heap1.Size()){
|
||||||
AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
|
AlternativeRoutingStep<false>(
|
||||||
|
reverse_heap1,
|
||||||
|
forward_heap1,
|
||||||
|
&middle_node,
|
||||||
|
&upper_bound_to_shortest_path_distance,
|
||||||
|
via_node_candidate_list,
|
||||||
|
reverse_search_space,
|
||||||
|
reverse_offset
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort_unique_resize(viaNodeCandidates);
|
sort_unique_resize(via_node_candidate_list);
|
||||||
|
|
||||||
std::vector<NodeID> packed_forward_path;
|
std::vector<NodeID> packed_forward_path;
|
||||||
std::vector<NodeID> packed_reverse_path;
|
std::vector<NodeID> packed_reverse_path;
|
||||||
|
|
||||||
super::RetrievePackedPathFromSingleHeap(forward_heap1, middle_node, packed_forward_path);
|
super::RetrievePackedPathFromSingleHeap(
|
||||||
super::RetrievePackedPathFromSingleHeap(reverse_heap1, middle_node, packed_reverse_path);
|
forward_heap1,
|
||||||
|
middle_node,
|
||||||
|
packed_forward_path
|
||||||
|
);
|
||||||
|
super::RetrievePackedPathFromSingleHeap(
|
||||||
|
reverse_heap1,
|
||||||
|
middle_node,
|
||||||
|
packed_reverse_path
|
||||||
|
);
|
||||||
|
|
||||||
boost::unordered_map<NodeID, int> approximated_forward_sharing;
|
boost::unordered_map<NodeID, int> approximated_forward_sharing;
|
||||||
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
|
boost::unordered_map<NodeID, int> approximated_reverse_sharing;
|
||||||
|
|
||||||
@@ -146,7 +216,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeID> nodes_that_passed_preselection;
|
std::vector<NodeID> nodes_that_passed_preselection;
|
||||||
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
|
BOOST_FOREACH(const NodeID node, via_node_candidate_list) {
|
||||||
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
|
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
|
||||||
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
|
int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
|
||||||
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
|
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
|
||||||
@@ -187,17 +257,17 @@ public:
|
|||||||
|
|
||||||
//Unpack shortest path and alternative, if they exist
|
//Unpack shortest path and alternative, if they exist
|
||||||
if(INT_MAX != upper_bound_to_shortest_path_distance) {
|
if(INT_MAX != upper_bound_to_shortest_path_distance) {
|
||||||
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
|
super::UnpackPath(packedShortestPath, raw_route_data.computedShortestPath);
|
||||||
rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
|
raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
|
||||||
} else {
|
} else {
|
||||||
rawRouteData.lengthOfShortestPath = INT_MAX;
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedViaNode != UINT_MAX) {
|
if(selectedViaNode != UINT_MAX) {
|
||||||
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
|
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, raw_route_data.computedAlternativePath);
|
||||||
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
|
raw_route_data.lengthOfAlternativePath = lengthOfViaPath;
|
||||||
} else {
|
} else {
|
||||||
rawRouteData.lengthOfAlternativePath = INT_MAX;
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,12 +289,14 @@ private:
|
|||||||
const int offset, const std::vector<NodeID> & packed_shortest_path) {
|
const int offset, const std::vector<NodeID> & packed_shortest_path) {
|
||||||
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
|
//compute and unpack <s,..,v> and <v,..,t> by exploring search spaces from v and intersecting against queues
|
||||||
//only half-searches have to be done at this stage
|
//only half-searches have to be done at this stage
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
|
QueryHeap & existingForwardHeap = *engine_working_data.forwardHeap;
|
||||||
QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
|
QueryHeap & existingBackwardHeap = *engine_working_data.backwardHeap;
|
||||||
QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
|
QueryHeap & newForwardHeap = *engine_working_data.forwardHeap2;
|
||||||
QueryHeap & newBackwardHeap = *super::_queryData.backwardHeap2;
|
QueryHeap & newBackwardHeap = *engine_working_data.backwardHeap2;
|
||||||
|
|
||||||
std::vector < NodeID > packed_s_v_path;
|
std::vector < NodeID > packed_s_v_path;
|
||||||
std::vector < NodeID > packed_v_t_path;
|
std::vector < NodeID > packed_v_t_path;
|
||||||
@@ -258,8 +330,8 @@ private:
|
|||||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||||
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
|
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) {
|
||||||
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
|
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
if (packed_s_v_path[i] == packed_shortest_path[i]) {
|
if (packed_s_v_path[i] == packed_shortest_path[i]) {
|
||||||
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
|
super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath);
|
||||||
@@ -270,8 +342,8 @@ private:
|
|||||||
}
|
}
|
||||||
//traverse partially unpacked edge and note common prefix
|
//traverse partially unpacked edge and note common prefix
|
||||||
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
|
for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
|
//Second, partially unpack v-->t in reverse order until paths deviate and note lengths
|
||||||
@@ -279,8 +351,8 @@ private:
|
|||||||
int shortestPathIndex = packed_shortest_path.size() - 1;
|
int shortestPathIndex = packed_shortest_path.size() - 1;
|
||||||
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
|
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) {
|
||||||
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
||||||
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
|
super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath);
|
||||||
@@ -294,8 +366,8 @@ private:
|
|||||||
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
|
shortestPathIndex = partiallyUnpackedShortestPath.size() - 1;
|
||||||
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
|
for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) {
|
||||||
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
|
if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
|
||||||
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += facade->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -315,8 +387,8 @@ private:
|
|||||||
//compute forward sharing
|
//compute forward sharing
|
||||||
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
||||||
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
|
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
|
||||||
sharing += search_graph->GetEdgeData(edgeID).distance;
|
sharing += facade->GetEdgeData(edgeID).distance;
|
||||||
++aindex;
|
++aindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,8 +396,8 @@ private:
|
|||||||
int bindex = packedShortestPath.size()-1;
|
int bindex = packedShortestPath.size()-1;
|
||||||
//compute backward sharing
|
//compute backward sharing
|
||||||
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
|
while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
|
||||||
sharing += search_graph->GetEdgeData(edgeID).distance;
|
sharing += facade->GetEdgeData(edgeID).distance;
|
||||||
--aindex; --bindex;
|
--aindex; --bindex;
|
||||||
}
|
}
|
||||||
return sharing;
|
return sharing;
|
||||||
@@ -363,12 +435,12 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
|
for ( EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); edge++ ) {
|
||||||
const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
||||||
if(forwardDirectionFlag) {
|
if(forwardDirectionFlag) {
|
||||||
|
|
||||||
const NodeID to = search_graph->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edgeWeight = data.distance;
|
const int edgeWeight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
@@ -438,8 +510,8 @@ private:
|
|||||||
std::stack<SearchSpaceEdge> unpackStack;
|
std::stack<SearchSpaceEdge> unpackStack;
|
||||||
//Traverse path s-->v
|
//Traverse path s-->v
|
||||||
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
|
for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||||
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
|
int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance;
|
||||||
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
||||||
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
|
unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]));
|
||||||
} else {
|
} else {
|
||||||
@@ -451,15 +523,15 @@ private:
|
|||||||
while (!unpackStack.empty()) {
|
while (!unpackStack.empty()) {
|
||||||
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
||||||
unpackStack.pop();
|
unpackStack.pop();
|
||||||
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||||
if(UINT_MAX == edgeIDInViaPath)
|
if(UINT_MAX == edgeIDInViaPath)
|
||||||
return false;
|
return false;
|
||||||
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
|
EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath);
|
||||||
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||||
if (IsViaEdgeShortCut) {
|
if (IsViaEdgeShortCut) {
|
||||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||||
typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
EdgeID edgeIDOfSecondSegment = facade->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||||
int lengthOfSecondSegment = search_graph->GetEdgeData(edgeIDOfSecondSegment).distance;
|
int lengthOfSecondSegment = facade->GetEdgeData(edgeIDOfSecondSegment).distance;
|
||||||
//attention: !unpacking in reverse!
|
//attention: !unpacking in reverse!
|
||||||
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
|
//Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one.
|
||||||
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
|
if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) {
|
||||||
@@ -479,8 +551,8 @@ private:
|
|||||||
unpackedUntilDistance = 0;
|
unpackedUntilDistance = 0;
|
||||||
//Traverse path s-->v
|
//Traverse path s-->v
|
||||||
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
||||||
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
||||||
int lengthOfCurrentEdge = search_graph->GetEdgeData(edgeID).distance;
|
int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance;
|
||||||
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) {
|
||||||
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
|
unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1]));
|
||||||
} else {
|
} else {
|
||||||
@@ -492,15 +564,15 @@ private:
|
|||||||
while (!unpackStack.empty()) {
|
while (!unpackStack.empty()) {
|
||||||
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
||||||
unpackStack.pop();
|
unpackStack.pop();
|
||||||
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||||
if(UINT_MAX == edgeIDInViaPath)
|
if(UINT_MAX == edgeIDInViaPath)
|
||||||
return false;
|
return false;
|
||||||
typename SearchGraph::EdgeData currentEdgeData = search_graph->GetEdgeData(edgeIDInViaPath);
|
EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath);
|
||||||
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
const bool IsViaEdgeShortCut = currentEdgeData.shortcut;
|
||||||
if (IsViaEdgeShortCut) {
|
if (IsViaEdgeShortCut) {
|
||||||
const NodeID middleOfViaPath = currentEdgeData.id;
|
const NodeID middleOfViaPath = currentEdgeData.id;
|
||||||
typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||||
int lengthOfFirstSegment = search_graph->GetEdgeData( edgeIDOfFirstSegment).distance;
|
int lengthOfFirstSegment = facade->GetEdgeData( edgeIDOfFirstSegment).distance;
|
||||||
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
|
//Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one.
|
||||||
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
|
if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) {
|
||||||
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath));
|
||||||
@@ -517,10 +589,12 @@ private:
|
|||||||
|
|
||||||
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
||||||
//Run actual T-Test query and compare if distances equal.
|
//Run actual T-Test query and compare if distances equal.
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
|
QueryHeap& forward_heap3 = *engine_working_data.forwardHeap3;
|
||||||
QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
|
QueryHeap& backward_heap3 = *engine_working_data.backwardHeap3;
|
||||||
int _upperBound = INT_MAX;
|
int _upperBound = INT_MAX;
|
||||||
NodeID middle = UINT_MAX;
|
NodeID middle = UINT_MAX;
|
||||||
forward_heap3.Insert(s_P, 0, s_P);
|
forward_heap3.Insert(s_P, 0, s_P);
|
||||||
|
|||||||
@@ -29,135 +29,180 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define BASICROUTINGINTERFACE_H_
|
#define BASICROUTINGINTERFACE_H_
|
||||||
|
|
||||||
#include "../DataStructures/RawRouteData.h"
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
#include "../Util/ContainerUtils.h"
|
#include "../Util/ContainerUtils.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
template<class QueryDataT>
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||||
class BasicRoutingInterface : boost::noncopyable{
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||||
|
SearchEngineData::SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
class BasicRoutingInterface : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
typedef typename DataFacadeT::EdgeData EdgeData;
|
||||||
protected:
|
protected:
|
||||||
QueryDataT & _queryData;
|
DataFacadeT * facade;
|
||||||
public:
|
public:
|
||||||
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
|
BasicRoutingInterface( DataFacadeT * facade ) : facade(facade) { }
|
||||||
virtual ~BasicRoutingInterface(){ };
|
virtual ~BasicRoutingInterface(){ };
|
||||||
|
|
||||||
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
inline void RoutingStep(
|
||||||
const NodeID node = _forwardHeap.DeleteMin();
|
SearchEngineData::QueryHeap & forward_heap,
|
||||||
const int distance = _forwardHeap.GetKey(node);
|
SearchEngineData::QueryHeap & reverse_heap,
|
||||||
//SimpleLogger().Write() << "Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance;
|
NodeID * middle_node_id,
|
||||||
if(_backwardHeap.WasInserted(node) ){
|
int * upper_bound,
|
||||||
const int newDistance = _backwardHeap.GetKey(node) + distance;
|
const int edge_expansion_offset,
|
||||||
if(newDistance < *_upperbound ){
|
const bool forward_direction
|
||||||
if(newDistance>=0 ) {
|
) const {
|
||||||
*middle = node;
|
const NodeID node = forward_heap.DeleteMin();
|
||||||
*_upperbound = newDistance;
|
const int distance = forward_heap.GetKey(node);
|
||||||
} else {
|
//SimpleLogger().Write() << "Settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance;
|
||||||
|
if(reverse_heap.WasInserted(node) ){
|
||||||
|
const int new_distance = reverse_heap.GetKey(node) + distance;
|
||||||
|
if(new_distance < *upper_bound ){
|
||||||
|
if( new_distance >= 0 ) {
|
||||||
|
*middle_node_id = node;
|
||||||
|
*upper_bound = new_distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(distance-edgeBasedOffset > *_upperbound){
|
if( (distance-edge_expansion_offset) > *upper_bound ){
|
||||||
_forwardHeap.DeleteAll();
|
forward_heap.DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Stalling
|
//Stalling
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
for(
|
||||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
EdgeID edge = facade->BeginEdges( node );
|
||||||
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
|
edge < facade->EndEdges(node);
|
||||||
if(backwardDirectionFlag) {
|
++edge
|
||||||
const NodeID to = _queryData.graph->GetTarget(edge);
|
) {
|
||||||
const int edgeWeight = data.distance;
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
|
const bool reverse_flag = (!forward_direction) ? data.forward : data.backward;
|
||||||
|
if( reverse_flag ) {
|
||||||
|
const NodeID to = facade->GetTarget(edge);
|
||||||
|
const int edge_weight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
||||||
|
|
||||||
if(_forwardHeap.WasInserted( to )) {
|
if(forward_heap.WasInserted( to )) {
|
||||||
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
|
if(forward_heap.GetKey( to ) + edge_weight < distance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
for(
|
||||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node);
|
||||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
edge < end_edge;
|
||||||
if(forwardDirectionFlag) {
|
++edge
|
||||||
|
) {
|
||||||
|
const EdgeData & data = facade->GetEdgeData(edge);
|
||||||
|
bool forward_directionFlag = (forward_direction ? data.forward : data.backward );
|
||||||
|
if( forward_directionFlag ) {
|
||||||
|
|
||||||
const NodeID to = _queryData.graph->GetTarget(edge);
|
const NodeID to = facade->GetTarget(edge);
|
||||||
const int edgeWeight = data.distance;
|
const int edge_weight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" );
|
||||||
const int toDistance = distance + edgeWeight;
|
const int to_distance = distance + edge_weight;
|
||||||
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !_forwardHeap.WasInserted( to ) ) {
|
if ( !forward_heap.WasInserted( to ) ) {
|
||||||
_forwardHeap.Insert( to, toDistance, node );
|
forward_heap.Insert( to, to_distance, node );
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < _forwardHeap.GetKey( to ) ) {
|
else if ( to_distance < forward_heap.GetKey( to ) ) {
|
||||||
_forwardHeap.GetData( to ).parent = node;
|
forward_heap.GetData( to ).parent = node;
|
||||||
_forwardHeap.DecreaseKey( to, toDistance );
|
forward_heap.DecreaseKey( to, to_distance );
|
||||||
//new parent
|
//new parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
|
inline void UnpackPath(
|
||||||
const unsigned sizeOfPackedPath = packedPath.size();
|
const std::vector<NodeID> & packed_path,
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
std::vector<_PathData> & unpacked_path
|
||||||
|
) const {
|
||||||
|
const unsigned packed_path_size = packed_path.size();
|
||||||
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||||
|
|
||||||
//We have to push the path in reverse order onto the stack because it's LIFO.
|
//We have to push the path in reverse order onto the stack because it's LIFO.
|
||||||
for(unsigned i = sizeOfPackedPath-1; i > 0; --i){
|
for(unsigned i = packed_path_size-1; i > 0; --i){
|
||||||
recursionStack.push(std::make_pair(packedPath[i-1], packedPath[i]));
|
recursion_stack.push(
|
||||||
|
std::make_pair(packed_path[i-1], packed_path[i])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while(!recursionStack.empty()) {
|
while(!recursion_stack.empty()) {
|
||||||
edge = recursionStack.top();
|
edge = recursion_stack.top();
|
||||||
recursionStack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int smallestWeight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.first);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
edge_id < facade->EndEdges(edge.first);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.second) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).forward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(smallestEdge == SPECIAL_EDGEID){
|
if( SPECIAL_EDGEID == smaller_edge_id ){
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.second);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
edge_id < facade->EndEdges(edge.second);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.first) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).backward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(smallestWeight != INT_MAX);
|
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge id invalid");
|
||||||
|
|
||||||
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
|
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||||
if(ed.shortcut) {//unpack
|
if( ed.shortcut ) {//unpack
|
||||||
const NodeID middle = ed.id;
|
const NodeID middle_node_id = ed.id;
|
||||||
//again, we need to this in reversed order
|
//again, we need to this in reversed order
|
||||||
recursionStack.push(std::make_pair(middle, edge.second));
|
recursion_stack.push(std::make_pair(middle_node_id, edge.second));
|
||||||
recursionStack.push(std::make_pair(edge.first, middle));
|
recursion_stack.push(std::make_pair(edge.first, middle_node_id));
|
||||||
} else {
|
} else {
|
||||||
assert(!ed.shortcut);
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
|
||||||
unpackedPath.push_back(
|
unpacked_path.push_back(
|
||||||
_PathData(
|
_PathData(
|
||||||
ed.id,
|
ed.id,
|
||||||
_queryData.nodeHelpDesk->GetNameIndexFromEdgeID(ed.id),
|
facade->GetNameIndexFromEdgeID(ed.id),
|
||||||
_queryData.nodeHelpDesk->GetTurnInstructionForEdgeID(ed.id),
|
facade->GetTurnInstructionForEdgeID(ed.id),
|
||||||
ed.distance
|
ed.distance
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -165,74 +210,112 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
|
inline void UnpackEdge(
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
const NodeID s,
|
||||||
recursionStack.push(std::make_pair(s,t));
|
const NodeID t,
|
||||||
|
std::vector<NodeID> & unpacked_path
|
||||||
|
) const {
|
||||||
|
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||||
|
recursion_stack.push(std::make_pair(s,t));
|
||||||
|
|
||||||
std::pair<NodeID, NodeID> edge;
|
std::pair<NodeID, NodeID> edge;
|
||||||
while(!recursionStack.empty()) {
|
while(!recursion_stack.empty()) {
|
||||||
edge = recursionStack.top();
|
edge = recursion_stack.top();
|
||||||
recursionStack.pop();
|
recursion_stack.pop();
|
||||||
|
|
||||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
EdgeID smaller_edge_id = SPECIAL_EDGEID;
|
||||||
int smallestWeight = INT_MAX;
|
int edge_weight = INT_MAX;
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.first);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
edge_id < facade->EndEdges(edge.first);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.second) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).forward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(smallestEdge == SPECIAL_EDGEID){
|
if( SPECIAL_EDGEID == smaller_edge_id ){
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
for(
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
EdgeID edge_id = facade->BeginEdges(edge.second);
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
edge_id < facade->EndEdges(edge.second);
|
||||||
smallestEdge = eit;
|
++edge_id
|
||||||
smallestWeight = weight;
|
){
|
||||||
|
const int weight = facade->GetEdgeData(edge_id).distance;
|
||||||
|
if(
|
||||||
|
(facade->GetTarget(edge_id) == edge.first) &&
|
||||||
|
(weight < edge_weight) &&
|
||||||
|
facade->GetEdgeData(edge_id).backward
|
||||||
|
){
|
||||||
|
smaller_edge_id = edge_id;
|
||||||
|
edge_weight = weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(smallestWeight != INT_MAX);
|
BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid");
|
||||||
|
|
||||||
const typename QueryDataT::Graph::EdgeData& ed = _queryData.graph->GetEdgeData(smallestEdge);
|
const EdgeData& ed = facade->GetEdgeData(smaller_edge_id);
|
||||||
if(ed.shortcut) {//unpack
|
if(ed.shortcut) {//unpack
|
||||||
const NodeID middle = ed.id;
|
const NodeID middle_node_id = ed.id;
|
||||||
//again, we need to this in reversed order
|
//again, we need to this in reversed order
|
||||||
recursionStack.push(std::make_pair(middle, edge.second));
|
recursion_stack.push(
|
||||||
recursionStack.push(std::make_pair(edge.first, middle));
|
std::make_pair(middle_node_id, edge.second)
|
||||||
|
);
|
||||||
|
recursion_stack.push(
|
||||||
|
std::make_pair(edge.first, middle_node_id)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
assert(!ed.shortcut);
|
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut");
|
||||||
unpackedPath.push_back(edge.first );
|
unpacked_path.push_back(edge.first );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unpackedPath.push_back(t);
|
unpacked_path.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
|
inline void RetrievePackedPathFromHeap(
|
||||||
NodeID pathNode = middle;
|
SearchEngineData::QueryHeap & forward_heap,
|
||||||
while(pathNode != _fHeap.GetData(pathNode).parent) {
|
SearchEngineData::QueryHeap & reverse_heap,
|
||||||
pathNode = _fHeap.GetData(pathNode).parent;
|
const NodeID middle_node_id,
|
||||||
packedPath.push_back(pathNode);
|
std::vector<NodeID> & packed_path
|
||||||
|
) const {
|
||||||
|
NodeID current_node_id = middle_node_id;
|
||||||
|
while(current_node_id != forward_heap.GetData(current_node_id).parent) {
|
||||||
|
current_node_id = forward_heap.GetData(current_node_id).parent;
|
||||||
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(packedPath.begin(), packedPath.end());
|
std::reverse(packed_path.begin(), packed_path.end());
|
||||||
packedPath.push_back(middle);
|
packed_path.push_back(middle_node_id);
|
||||||
pathNode = middle;
|
current_node_id = middle_node_id;
|
||||||
while (pathNode != _bHeap.GetData(pathNode).parent){
|
while (current_node_id != reverse_heap.GetData(current_node_id).parent){
|
||||||
pathNode = _bHeap.GetData(pathNode).parent;
|
current_node_id = reverse_heap.GetData(current_node_id).parent;
|
||||||
packedPath.push_back(pathNode);
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
|
//TODO: reorder parameters
|
||||||
NodeID pathNode = middle;
|
inline void RetrievePackedPathFromSingleHeap(
|
||||||
while(pathNode != search_heap.GetData(pathNode).parent) {
|
SearchEngineData::QueryHeap & search_heap,
|
||||||
pathNode = search_heap.GetData(pathNode).parent;
|
const NodeID middle_node_id,
|
||||||
packed_path.push_back(pathNode);
|
std::vector<NodeID>& packed_path
|
||||||
|
) const {
|
||||||
|
NodeID current_node_id = middle_node_id;
|
||||||
|
while(current_node_id != search_heap.GetData(current_node_id).parent) {
|
||||||
|
current_node_id = search_heap.GetData(current_node_id).parent;
|
||||||
|
packed_path.push_back(current_node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ComputeEdgeOffset(const PhantomNode & phantom) const {
|
||||||
|
return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* BASICROUTINGINTERFACE_H_ */
|
#endif /* BASICROUTINGINTERFACE_H_ */
|
||||||
|
|||||||
@@ -28,176 +28,314 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef SHORTESTPATHROUTING_H_
|
#ifndef SHORTESTPATHROUTING_H_
|
||||||
#define SHORTESTPATHROUTING_H_
|
#define SHORTESTPATHROUTING_H_
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include "../DataStructures/SearchEngineData.h"
|
||||||
|
|
||||||
|
template<class DataFacadeT>
|
||||||
|
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
|
||||||
|
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||||
|
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||||
|
SearchEngineData & engine_working_data;
|
||||||
|
|
||||||
template<class QueryDataT>
|
|
||||||
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
|
|
||||||
typedef BasicRoutingInterface<QueryDataT> super;
|
|
||||||
typedef typename QueryDataT::QueryHeap QueryHeap;
|
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
|
ShortestPathRouting(
|
||||||
|
DataFacadeT * facade,
|
||||||
|
SearchEngineData & engine_working_data
|
||||||
|
) :
|
||||||
|
super(facade),
|
||||||
|
engine_working_data(engine_working_data)
|
||||||
|
{}
|
||||||
|
|
||||||
~ShortestPathRouting() {}
|
~ShortestPathRouting() {}
|
||||||
|
|
||||||
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
|
void operator()(
|
||||||
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
RawRouteData & raw_route_data
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
) const {
|
||||||
|
BOOST_FOREACH(
|
||||||
|
const PhantomNodes & phantom_node_pair,
|
||||||
|
phantom_nodes_vector
|
||||||
|
){
|
||||||
|
if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||||
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int distance1 = 0;
|
int distance1 = 0;
|
||||||
int distance2 = 0;
|
int distance2 = 0;
|
||||||
|
|
||||||
bool searchFrom1stStartNode = true;
|
bool search_from_1st_node = true;
|
||||||
bool searchFrom2ndStartNode = true;
|
bool search_from_2nd_node = true;
|
||||||
NodeID middle1 = UINT_MAX;
|
NodeID middle1 = UINT_MAX;
|
||||||
NodeID middle2 = UINT_MAX;
|
NodeID middle2 = UINT_MAX;
|
||||||
std::vector<NodeID> packedPath1;
|
std::vector<NodeID> packed_path1;
|
||||||
std::vector<NodeID> packedPath2;
|
std::vector<NodeID> packed_path2;
|
||||||
|
|
||||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
super::facade->GetNumberOfNodes()
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
);
|
||||||
|
engine_working_data.InitializeOrClearSecondThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||||
|
super::facade->GetNumberOfNodes()
|
||||||
|
);
|
||||||
|
|
||||||
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
QueryHeap & forward_heap1 = *(engine_working_data.forwardHeap);
|
||||||
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
QueryHeap & reverse_heap1 = *(engine_working_data.backwardHeap);
|
||||||
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
||||||
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
||||||
|
|
||||||
//Get distance to next pair of target nodes.
|
//Get distance to next pair of target nodes.
|
||||||
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
BOOST_FOREACH(
|
||||||
|
const PhantomNodes & phantom_node_pair,
|
||||||
|
phantom_nodes_vector
|
||||||
|
){
|
||||||
forward_heap1.Clear(); forward_heap2.Clear();
|
forward_heap1.Clear(); forward_heap2.Clear();
|
||||||
reverse_heap1.Clear(); reverse_heap2.Clear();
|
reverse_heap1.Clear(); reverse_heap2.Clear();
|
||||||
int _localUpperbound1 = INT_MAX;
|
int local_upper_bound1 = INT_MAX;
|
||||||
int _localUpperbound2 = INT_MAX;
|
int local_upper_bound2 = INT_MAX;
|
||||||
|
|
||||||
middle1 = UINT_MAX;
|
middle1 = UINT_MAX;
|
||||||
middle2 = UINT_MAX;
|
middle2 = UINT_MAX;
|
||||||
|
|
||||||
//insert new starting nodes into forward heap, adjusted by previous distances.
|
//insert new starting nodes into forward heap, adjusted by previous distances.
|
||||||
if(searchFrom1stStartNode) {
|
if(search_from_1st_node) {
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap1.Insert(
|
||||||
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, distance1-phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
distance1-phantom_node_pair.startPhantom.weight1,
|
||||||
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
phantom_node_pair.startPhantom.edgeBasedNode
|
||||||
|
);
|
||||||
|
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
|
forward_heap2.Insert(
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||||
|
distance1-phantom_node_pair.startPhantom.weight1,
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode
|
||||||
|
);
|
||||||
|
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
}
|
}
|
||||||
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(
|
||||||
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, distance2-phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
distance2-phantom_node_pair.startPhantom.weight2,
|
||||||
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
|
forward_heap2.Insert(
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||||
|
distance2-phantom_node_pair.startPhantom.weight2,
|
||||||
|
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//insert new backward nodes into backward heap, unadjusted.
|
//insert new backward nodes into backward heap, unadjusted.
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
reverse_heap1.Insert(
|
||||||
// INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
|
phantom_node_pair.targetPhantom.edgeBasedNode,
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
phantom_node_pair.targetPhantom.weight1,
|
||||||
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
phantom_node_pair.targetPhantom.edgeBasedNode
|
||||||
// INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
|
);
|
||||||
|
// INFO("rv1: " << phantom_node_pair.targetPhantom.edgeBasedNode << ", w;" << phantom_node_pair.targetPhantom.weight1 );
|
||||||
|
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
||||||
|
reverse_heap2.Insert(
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
||||||
|
phantom_node_pair.targetPhantom.weight2,
|
||||||
|
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
||||||
|
);
|
||||||
|
// INFO("rv2: " << phantom_node_pair.targetPhantom.edgeBasedNode+1 << ", w;" << phantom_node_pair.targetPhantom.weight2 );
|
||||||
}
|
}
|
||||||
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
const int forward_offset = super::ComputeEdgeOffset(
|
||||||
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
phantom_node_pair.startPhantom
|
||||||
|
);
|
||||||
|
const int reverse_offset = super::ComputeEdgeOffset(
|
||||||
|
phantom_node_pair.targetPhantom
|
||||||
|
);
|
||||||
|
|
||||||
//run two-Target Dijkstra routing step.
|
//run two-Target Dijkstra routing step.
|
||||||
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
||||||
if(0 < forward_heap1.Size()){
|
if( !forward_heap1.Empty()){
|
||||||
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
|
super::RoutingStep(
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
&middle1,
|
||||||
|
&local_upper_bound1,
|
||||||
|
forward_offset,
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap1.Size() ){
|
if( !reverse_heap1.Empty() ){
|
||||||
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
|
super::RoutingStep(
|
||||||
|
reverse_heap1,
|
||||||
|
forward_heap1,
|
||||||
|
&middle1,
|
||||||
|
&local_upper_bound1,
|
||||||
|
reverse_offset,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap2.Size()) {
|
if( !reverse_heap2.Empty() ) {
|
||||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||||
if(0 < forward_heap2.Size()){
|
if( !forward_heap2.Empty() ){
|
||||||
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
|
super::RoutingStep(
|
||||||
|
forward_heap2,
|
||||||
|
reverse_heap2,
|
||||||
|
&middle2,
|
||||||
|
&local_upper_bound2,
|
||||||
|
forward_offset,
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if(0 < reverse_heap2.Size()){
|
if( !reverse_heap2.Empty() ){
|
||||||
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
|
super::RoutingStep(
|
||||||
|
reverse_heap2,
|
||||||
|
forward_heap2,
|
||||||
|
&middle2,
|
||||||
|
&local_upper_bound2,
|
||||||
|
reverse_offset,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//No path found for both target nodes?
|
//No path found for both target nodes?
|
||||||
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
|
if(
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
(INT_MAX == local_upper_bound1) &&
|
||||||
|
(INT_MAX == local_upper_bound2)
|
||||||
|
) {
|
||||||
|
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||||
|
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle1) {
|
if(UINT_MAX == middle1) {
|
||||||
searchFrom1stStartNode = false;
|
search_from_1st_node = false;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle2) {
|
if(UINT_MAX == middle2) {
|
||||||
searchFrom2ndStartNode = false;
|
search_from_2nd_node = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Was at most one of the two paths not found?
|
//Was at most one of the two paths not found?
|
||||||
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
|
BOOST_ASSERT_MSG(
|
||||||
|
(INT_MAX != distance1 || INT_MAX != distance2),
|
||||||
|
"no path found"
|
||||||
|
);
|
||||||
|
|
||||||
//Unpack paths if they exist
|
//Unpack paths if they exist
|
||||||
std::vector<NodeID> temporaryPackedPath1;
|
std::vector<NodeID> temporary_packed_path1;
|
||||||
std::vector<NodeID> temporaryPackedPath2;
|
std::vector<NodeID> temporary_packed_path2;
|
||||||
if(INT_MAX != _localUpperbound1) {
|
if(INT_MAX != local_upper_bound1) {
|
||||||
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
|
super::RetrievePackedPathFromHeap(
|
||||||
|
forward_heap1,
|
||||||
|
reverse_heap1,
|
||||||
|
middle1,
|
||||||
|
temporary_packed_path1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(INT_MAX != _localUpperbound2) {
|
if(INT_MAX != local_upper_bound2) {
|
||||||
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
|
super::RetrievePackedPathFromHeap(
|
||||||
|
forward_heap2,
|
||||||
|
reverse_heap2,
|
||||||
|
middle2,
|
||||||
|
temporary_packed_path2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if one of the paths was not found, replace it with the other one.
|
//if one of the paths was not found, replace it with the other one.
|
||||||
if(0 == temporaryPackedPath1.size()) {
|
if( temporary_packed_path1.empty() ) {
|
||||||
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
temporary_packed_path1.insert(
|
||||||
_localUpperbound1 = _localUpperbound2;
|
temporary_packed_path1.end(),
|
||||||
|
temporary_packed_path2.begin(),
|
||||||
|
temporary_packed_path2.end()
|
||||||
|
);
|
||||||
|
local_upper_bound1 = local_upper_bound2;
|
||||||
}
|
}
|
||||||
if(0 == temporaryPackedPath2.size()) {
|
if( temporary_packed_path2.empty() ) {
|
||||||
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
temporary_packed_path2.insert(
|
||||||
_localUpperbound2 = _localUpperbound1;
|
temporary_packed_path2.end(),
|
||||||
|
temporary_packed_path1.begin(),
|
||||||
|
temporary_packed_path1.end()
|
||||||
|
);
|
||||||
|
local_upper_bound2 = local_upper_bound1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(0 < temporaryPackedPath1.size() && 0 < temporaryPackedPath2.size());
|
BOOST_ASSERT_MSG(
|
||||||
|
!temporary_packed_path1.empty() ||
|
||||||
|
!temporary_packed_path2.empty(),
|
||||||
|
"tempory packed paths empty"
|
||||||
|
);
|
||||||
|
|
||||||
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
||||||
if(0 < packedPath1.size() && 0 < packedPath2.size() ) {
|
if( !packed_path1.empty() && !packed_path2.empty() ) {
|
||||||
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
|
if(
|
||||||
//both new route segments start with the same node, thus one of the packedPath must go.
|
temporary_packed_path1.front() ==
|
||||||
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
|
temporary_packed_path2.front()
|
||||||
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
|
) {
|
||||||
packedPath2.clear();
|
//both new route segments start with the same node
|
||||||
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
|
//thus, one of the packedPath must go.
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
(packed_path1.size() == packed_path2.size() ) ||
|
||||||
|
(packed_path1.back() != packed_path2.back() ),
|
||||||
|
"packed paths must be different"
|
||||||
|
);
|
||||||
|
|
||||||
|
if( packed_path1.back() == temporary_packed_path1.front()) {
|
||||||
|
packed_path2.clear();
|
||||||
|
packed_path2.insert(
|
||||||
|
packed_path2.end(),
|
||||||
|
packed_path1.begin(),
|
||||||
|
packed_path1.end()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
packedPath1.clear();
|
packed_path1.clear();
|
||||||
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
|
packed_path1.insert(
|
||||||
|
packed_path1.end(),
|
||||||
|
packed_path2.begin(),
|
||||||
|
packed_path2.end()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//packed paths 1 and 2 may need to switch.
|
//packed paths 1 and 2 may need to switch.
|
||||||
if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
|
if( packed_path1.back() != temporary_packed_path1.front()) {
|
||||||
packedPath1.swap(packedPath2);
|
packed_path1.swap(packed_path2);
|
||||||
std::swap(distance1, distance2);
|
std::swap(distance1, distance2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
packed_path1.insert(
|
||||||
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
packed_path1.end(),
|
||||||
|
temporary_packed_path1.begin(),
|
||||||
|
temporary_packed_path1.end()
|
||||||
|
);
|
||||||
|
packed_path2.insert(
|
||||||
|
packed_path2.end(),
|
||||||
|
temporary_packed_path2.begin(),
|
||||||
|
temporary_packed_path2.end()
|
||||||
|
);
|
||||||
|
|
||||||
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
|
if(
|
||||||
|
(packed_path1.back() == packed_path2.back()) &&
|
||||||
NodeID lastNodeID = packedPath2.back();
|
phantom_node_pair.targetPhantom.isBidirected()
|
||||||
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
|
) {
|
||||||
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
|
const NodeID last_node_id = packed_path2.back();
|
||||||
|
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
|
||||||
|
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
distance1 = _localUpperbound1;
|
distance1 = local_upper_bound1;
|
||||||
distance2 = _localUpperbound2;
|
distance2 = local_upper_bound2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(distance1 > distance2){
|
if( distance1 > distance2 ) {
|
||||||
std::swap(packedPath1, packedPath2);
|
std::swap( packed_path1, packed_path2 );
|
||||||
}
|
}
|
||||||
remove_consecutive_duplicates_from_vector(packedPath1);
|
remove_consecutive_duplicates_from_vector(packed_path1);
|
||||||
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
super::UnpackPath(packed_path1, raw_route_data.computedShortestPath);
|
||||||
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
|
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BASIC_DATASTRUCTURES_H
|
|
||||||
#define BASIC_DATASTRUCTURES_H
|
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
|
||||||
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
|
||||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
|
||||||
|
|
||||||
const char okHTML[] = "";
|
|
||||||
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
|
||||||
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
|
||||||
const char seperators[] = { ':', ' ' };
|
|
||||||
const char crlf[] = { '\r', '\n' };
|
|
||||||
|
|
||||||
struct Header {
|
|
||||||
std::string name;
|
|
||||||
std::string value;
|
|
||||||
void Clear() {
|
|
||||||
name.clear();
|
|
||||||
value.clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum CompressionType {
|
|
||||||
noCompression,
|
|
||||||
gzipRFC1952,
|
|
||||||
deflateRFC1951
|
|
||||||
} Compression;
|
|
||||||
|
|
||||||
struct Request {
|
|
||||||
std::string uri;
|
|
||||||
std::string referrer;
|
|
||||||
std::string agent;
|
|
||||||
boost::asio::ip::address endpoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Reply {
|
|
||||||
Reply() : status(ok) { content.reserve(2 << 20); }
|
|
||||||
enum status_type {
|
|
||||||
ok = 200,
|
|
||||||
badRequest = 400,
|
|
||||||
internalServerError = 500
|
|
||||||
} status;
|
|
||||||
|
|
||||||
std::vector<Header> headers;
|
|
||||||
std::vector<boost::asio::const_buffer> toBuffers();
|
|
||||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
|
||||||
std::string content;
|
|
||||||
static Reply stockReply(status_type status);
|
|
||||||
void setSize(const unsigned size) {
|
|
||||||
BOOST_FOREACH ( Header& h, headers) {
|
|
||||||
if("Content-Length" == h.name) {
|
|
||||||
std::string sizeString;
|
|
||||||
intToString(size,h.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
boost::asio::const_buffer ToBuffer(Reply::status_type status) {
|
|
||||||
switch (status) {
|
|
||||||
case Reply::ok:
|
|
||||||
return boost::asio::buffer(okString);
|
|
||||||
case Reply::internalServerError:
|
|
||||||
return boost::asio::buffer(internalServerErrorString);
|
|
||||||
default:
|
|
||||||
return boost::asio::buffer(badRequestString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToString(Reply::status_type status) {
|
|
||||||
switch (status) {
|
|
||||||
case Reply::ok:
|
|
||||||
return okHTML;
|
|
||||||
case Reply::badRequest:
|
|
||||||
return badRequestHTML;
|
|
||||||
default:
|
|
||||||
return internalServerErrorHTML;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
|
|
||||||
std::vector<boost::asio::const_buffer> buffers;
|
|
||||||
buffers.push_back(ToBuffer(status));
|
|
||||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
|
||||||
Header& h = headers[i];
|
|
||||||
buffers.push_back(boost::asio::buffer(h.name));
|
|
||||||
buffers.push_back(boost::asio::buffer(seperators));
|
|
||||||
buffers.push_back(boost::asio::buffer(h.value));
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
}
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
buffers.push_back(boost::asio::buffer(content));
|
|
||||||
return buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
|
|
||||||
std::vector<boost::asio::const_buffer> buffers;
|
|
||||||
buffers.push_back(ToBuffer(status));
|
|
||||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
|
||||||
Header& h = headers[i];
|
|
||||||
buffers.push_back(boost::asio::buffer(h.name));
|
|
||||||
buffers.push_back(boost::asio::buffer(seperators));
|
|
||||||
buffers.push_back(boost::asio::buffer(h.value));
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
}
|
|
||||||
buffers.push_back(boost::asio::buffer(crlf));
|
|
||||||
return buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reply Reply::stockReply(Reply::status_type status) {
|
|
||||||
Reply rep;
|
|
||||||
rep.status = status;
|
|
||||||
rep.content = ToString(status);
|
|
||||||
rep.headers.resize(3);
|
|
||||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
|
||||||
rep.headers[0].value = "*";
|
|
||||||
rep.headers[1].name = "Content-Length";
|
|
||||||
|
|
||||||
std::string s;
|
|
||||||
intToString(rep.content.size(), s);
|
|
||||||
|
|
||||||
rep.headers[1].value = s;
|
|
||||||
rep.headers[2].name = "Content-Type";
|
|
||||||
rep.headers[2].value = "text/html";
|
|
||||||
return rep;
|
|
||||||
}
|
|
||||||
} // namespace http
|
|
||||||
|
|
||||||
#endif //BASIC_DATASTRUCTURES_H
|
|
||||||
+101
-70
@@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef CONNECTION_H
|
#ifndef CONNECTION_H
|
||||||
#define CONNECTION_H
|
#define CONNECTION_H
|
||||||
|
|
||||||
#include "BasicDatastructures.h"
|
#include "Http/CompressionType.h"
|
||||||
#include "RequestHandler.h"
|
#include "RequestHandler.h"
|
||||||
#include "RequestParser.h"
|
#include "RequestParser.h"
|
||||||
|
|
||||||
@@ -37,11 +37,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/iostreams/filtering_stream.hpp>
|
||||||
|
#include <boost/iostreams/filter/gzip.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
|
// #include <zlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
@@ -92,7 +96,7 @@ private:
|
|||||||
request_handler.handle_request(request, reply);
|
request_handler.handle_request(request, reply);
|
||||||
|
|
||||||
Header compression_header;
|
Header compression_header;
|
||||||
std::vector<unsigned char> compressed_output;
|
std::vector<char> compressed_output;
|
||||||
std::vector<boost::asio::const_buffer> output_buffer;
|
std::vector<boost::asio::const_buffer> output_buffer;
|
||||||
switch(compression_type) {
|
switch(compression_type) {
|
||||||
case deflateRFC1951:
|
case deflateRFC1951:
|
||||||
@@ -102,11 +106,10 @@ private:
|
|||||||
reply.headers.begin(),
|
reply.headers.begin(),
|
||||||
compression_header
|
compression_header
|
||||||
);
|
);
|
||||||
compressCharArray(
|
compressBufferCollection(
|
||||||
reply.content.c_str(),
|
reply.content,
|
||||||
reply.content.length(),
|
compression_type,
|
||||||
compressed_output,
|
compressed_output
|
||||||
compression_type
|
|
||||||
);
|
);
|
||||||
reply.setSize(compressed_output.size());
|
reply.setSize(compressed_output.size());
|
||||||
output_buffer = reply.HeaderstoBuffers();
|
output_buffer = reply.HeaderstoBuffers();
|
||||||
@@ -132,11 +135,10 @@ private:
|
|||||||
reply.headers.begin(),
|
reply.headers.begin(),
|
||||||
compression_header
|
compression_header
|
||||||
);
|
);
|
||||||
compressCharArray(
|
compressBufferCollection(
|
||||||
reply.content.c_str(),
|
reply.content,
|
||||||
reply.content.length(),
|
compression_type,
|
||||||
compressed_output,
|
compressed_output
|
||||||
compression_type
|
|
||||||
);
|
);
|
||||||
reply.setSize(compressed_output.size());
|
reply.setSize(compressed_output.size());
|
||||||
output_buffer = reply.HeaderstoBuffers();
|
output_buffer = reply.HeaderstoBuffers();
|
||||||
@@ -170,7 +172,7 @@ private:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (!result) {
|
} else if (!result) {
|
||||||
reply = Reply::stockReply(Reply::badRequest);
|
reply = Reply::StockReply(Reply::badRequest);
|
||||||
boost::asio::async_write(
|
boost::asio::async_write(
|
||||||
TCP_socket,
|
TCP_socket,
|
||||||
reply.toBuffers(),
|
reply.toBuffers(),
|
||||||
@@ -210,71 +212,100 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compressBufferCollection(
|
||||||
|
std::vector<std::string> uncompressed_data,
|
||||||
|
CompressionType compression_type,
|
||||||
|
std::vector<char> & compressed_data
|
||||||
|
) {
|
||||||
|
boost::iostreams::gzip_params compression_parameters;
|
||||||
|
|
||||||
|
compression_parameters.level = boost::iostreams::zlib::best_speed;
|
||||||
|
if ( deflateRFC1951 == compression_type ) {
|
||||||
|
compression_parameters.noheader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT( compressed_data.empty() );
|
||||||
|
boost::iostreams::filtering_ostream compressing_stream;
|
||||||
|
|
||||||
|
compressing_stream.push(
|
||||||
|
boost::iostreams::gzip_compressor(compression_parameters)
|
||||||
|
);
|
||||||
|
compressing_stream.push(
|
||||||
|
boost::iostreams::back_inserter(compressed_data)
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_FOREACH( const std::string & line, uncompressed_data) {
|
||||||
|
compressing_stream << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
compressing_stream.reset();
|
||||||
|
}
|
||||||
|
|
||||||
// Big thanks to deusty who explains how to use gzip compression by
|
// Big thanks to deusty who explains how to use gzip compression by
|
||||||
// the right call to deflateInit2():
|
// the right call to deflateInit2():
|
||||||
// http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
|
// http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
|
||||||
void compressCharArray(
|
// void compressCharArray(
|
||||||
const char * in_data,
|
// const char * in_data,
|
||||||
size_t in_data_size,
|
// size_t in_data_size,
|
||||||
std::vector<unsigned char> & buffer,
|
// std::vector<unsigned char> & buffer,
|
||||||
CompressionType type
|
// CompressionType type
|
||||||
) {
|
// ) {
|
||||||
const size_t BUFSIZE = 128 * 1024;
|
// const size_t BUFSIZE = 128 * 1024;
|
||||||
unsigned char temp_buffer[BUFSIZE];
|
// unsigned char temp_buffer[BUFSIZE];
|
||||||
|
|
||||||
z_stream strm;
|
// z_stream strm;
|
||||||
strm.zalloc = Z_NULL;
|
// strm.zalloc = Z_NULL;
|
||||||
strm.zfree = Z_NULL;
|
// strm.zfree = Z_NULL;
|
||||||
strm.opaque = Z_NULL;
|
// strm.opaque = Z_NULL;
|
||||||
strm.total_out = 0;
|
// strm.total_out = 0;
|
||||||
strm.next_in = (unsigned char *)(in_data);
|
// strm.next_in = (unsigned char *)(in_data);
|
||||||
strm.avail_in = in_data_size;
|
// strm.avail_in = in_data_size;
|
||||||
strm.next_out = temp_buffer;
|
// strm.next_out = temp_buffer;
|
||||||
strm.avail_out = BUFSIZE;
|
// strm.avail_out = BUFSIZE;
|
||||||
strm.data_type = Z_ASCII;
|
// strm.data_type = Z_ASCII;
|
||||||
|
|
||||||
switch(type){
|
// switch(type){
|
||||||
case deflateRFC1951:
|
// case deflateRFC1951:
|
||||||
deflateInit(&strm, Z_BEST_SPEED);
|
// deflateInit(&strm, Z_BEST_SPEED);
|
||||||
break;
|
// break;
|
||||||
case gzipRFC1952:
|
// case gzipRFC1952:
|
||||||
deflateInit2(
|
// deflateInit2(
|
||||||
&strm,
|
// &strm,
|
||||||
Z_DEFAULT_COMPRESSION,
|
// Z_DEFAULT_COMPRESSION,
|
||||||
Z_DEFLATED,
|
// Z_DEFLATED,
|
||||||
(15+16),
|
// (15+16),
|
||||||
9,
|
// 9,
|
||||||
Z_DEFAULT_STRATEGY
|
// Z_DEFAULT_STRATEGY
|
||||||
);
|
// );
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
BOOST_ASSERT_MSG(false, "should not happen");
|
// BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
int deflate_res = Z_OK;
|
// int deflate_res = Z_OK;
|
||||||
do {
|
// do {
|
||||||
if ( 0 == strm.avail_out ) {
|
// if ( 0 == strm.avail_out ) {
|
||||||
buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
|
// buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
|
||||||
strm.next_out = temp_buffer;
|
// strm.next_out = temp_buffer;
|
||||||
strm.avail_out = BUFSIZE;
|
// strm.avail_out = BUFSIZE;
|
||||||
}
|
// }
|
||||||
deflate_res = deflate(&strm, Z_FINISH);
|
// deflate_res = deflate(&strm, Z_FINISH);
|
||||||
|
|
||||||
} while (deflate_res == Z_OK);
|
// } while (deflate_res == Z_OK);
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(
|
// BOOST_ASSERT_MSG(
|
||||||
deflate_res == Z_STREAM_END,
|
// deflate_res == Z_STREAM_END,
|
||||||
"compression not properly finished"
|
// "compression not properly finished"
|
||||||
);
|
// );
|
||||||
|
|
||||||
buffer.insert(
|
// buffer.insert(
|
||||||
buffer.end(),
|
// buffer.end(),
|
||||||
temp_buffer,
|
// temp_buffer,
|
||||||
temp_buffer + BUFSIZE - strm.avail_out
|
// temp_buffer + BUFSIZE - strm.avail_out
|
||||||
);
|
// );
|
||||||
deflateEnd(&strm);
|
// deflateEnd(&strm);
|
||||||
}
|
// }
|
||||||
|
|
||||||
boost::asio::io_service::strand strand;
|
boost::asio::io_service::strand strand;
|
||||||
boost::asio::ip::tcp::socket TCP_socket;
|
boost::asio::ip::tcp::socket TCP_socket;
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QUERY_DATA_FACADE_H
|
||||||
|
#define QUERY_DATA_FACADE_H
|
||||||
|
|
||||||
|
//Exposes all data access interfaces to the algorithms via base class ptr
|
||||||
|
|
||||||
|
#include "../../DataStructures/Coordinate.h"
|
||||||
|
#include "../../DataStructures/EdgeBasedNode.h"
|
||||||
|
#include "../../DataStructures/ImportNode.h"
|
||||||
|
#include "../../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../../DataStructures/TurnInstructions.h"
|
||||||
|
#include "../../Util/OSRMException.h"
|
||||||
|
#include "../../Util/StringUtil.h"
|
||||||
|
#include "../../typedefs.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
template<class EdgeDataT>
|
||||||
|
class BaseDataFacade {
|
||||||
|
public:
|
||||||
|
typedef EdgeBasedNode RTreeLeaf;
|
||||||
|
typedef EdgeDataT EdgeData;
|
||||||
|
BaseDataFacade( ) { }
|
||||||
|
virtual ~BaseDataFacade() { }
|
||||||
|
|
||||||
|
//search graph access
|
||||||
|
virtual unsigned GetNumberOfNodes() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetNumberOfEdges() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetOutDegree( const NodeID n ) const = 0;
|
||||||
|
|
||||||
|
virtual NodeID GetTarget( const EdgeID e ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeDataT &GetEdgeData( const EdgeID e ) = 0;
|
||||||
|
|
||||||
|
// virtual const EdgeDataT &GetEdgeData( const EdgeID e ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID BeginEdges( const NodeID n ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID EndEdges( const NodeID n ) const = 0;
|
||||||
|
|
||||||
|
//searches for a specific edge
|
||||||
|
virtual EdgeID FindEdge( const NodeID from, const NodeID to ) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID FindEdgeInEitherDirection(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual EdgeID FindEdgeIndicateIfReverse(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to,
|
||||||
|
bool & result
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
//node and edge information access
|
||||||
|
virtual FixedPointCoordinate GetCoordinateOfNode(
|
||||||
|
const unsigned id
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
|
const unsigned id
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual bool LocateClosestEndPointForCoordinate(
|
||||||
|
const FixedPointCoordinate& input_coordinate,
|
||||||
|
FixedPointCoordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetCheckSum() const = 0;
|
||||||
|
|
||||||
|
virtual unsigned GetNameIndexFromEdgeID(const unsigned id) const = 0;
|
||||||
|
|
||||||
|
virtual void GetName(
|
||||||
|
const unsigned name_id,
|
||||||
|
std::string & result
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
std::string GetEscapedNameForNameID(const unsigned name_id) const {
|
||||||
|
std::string temporary_string;
|
||||||
|
GetName(name_id, temporary_string);
|
||||||
|
return HTMLEntitize(temporary_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string GetTimestamp() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QUERY_DATA_FACADE_H
|
||||||
@@ -0,0 +1,396 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INTERNAL_DATA_FACADE
|
||||||
|
#define INTERNAL_DATA_FACADE
|
||||||
|
|
||||||
|
//implements all data storage when shared memory is _NOT_ used
|
||||||
|
|
||||||
|
#include "BaseDataFacade.h"
|
||||||
|
|
||||||
|
#include "../../DataStructures/Coordinate.h"
|
||||||
|
#include "../../DataStructures/QueryNode.h"
|
||||||
|
#include "../../DataStructures/QueryEdge.h"
|
||||||
|
#include "../../DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
|
#include "../../DataStructures/StaticGraph.h"
|
||||||
|
#include "../../DataStructures/StaticRTree.h"
|
||||||
|
#include "../../Util/BoostFileSystemFix.h"
|
||||||
|
#include "../../Util/GraphLoader.h"
|
||||||
|
#include "../../Util/IniFile.h"
|
||||||
|
#include "../../Util/ProgramOptions.h"
|
||||||
|
#include "../../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
template<class EdgeDataT>
|
||||||
|
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef BaseDataFacade<EdgeDataT> super;
|
||||||
|
typedef StaticGraph<typename super::EdgeData> QueryGraph;
|
||||||
|
typedef typename QueryGraph::InputEdge InputEdge;
|
||||||
|
typedef typename super::RTreeLeaf RTreeLeaf;
|
||||||
|
|
||||||
|
InternalDataFacade() { }
|
||||||
|
|
||||||
|
unsigned m_check_sum;
|
||||||
|
unsigned m_number_of_nodes;
|
||||||
|
QueryGraph * m_query_graph;
|
||||||
|
std::string m_timestamp;
|
||||||
|
|
||||||
|
ShM<FixedPointCoordinate, false>::vector m_coordinate_list;
|
||||||
|
ShM<NodeID, false>::vector m_via_node_list;
|
||||||
|
ShM<unsigned, false>::vector m_name_ID_list;
|
||||||
|
ShM<TurnInstruction, false>::vector m_turn_instruction_list;
|
||||||
|
ShM<char, false>::vector m_names_char_list;
|
||||||
|
ShM<unsigned, false>::vector m_name_begin_indices;
|
||||||
|
|
||||||
|
StaticRTree<RTreeLeaf, false> * m_static_rtree;
|
||||||
|
|
||||||
|
|
||||||
|
void LoadTimestamp(const boost::filesystem::path & timestamp_path) {
|
||||||
|
if( boost::filesystem::exists(timestamp_path) ) {
|
||||||
|
SimpleLogger().Write() << "Loading Timestamp";
|
||||||
|
boost::filesystem::ifstream timestampInStream( timestamp_path );
|
||||||
|
if(!timestampInStream) {
|
||||||
|
SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
|
||||||
|
}
|
||||||
|
getline(timestampInStream, m_timestamp);
|
||||||
|
timestampInStream.close();
|
||||||
|
}
|
||||||
|
if(m_timestamp.empty()) {
|
||||||
|
m_timestamp = "n/a";
|
||||||
|
}
|
||||||
|
if(25 < m_timestamp.length()) {
|
||||||
|
m_timestamp.resize(25);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadGraph(const boost::filesystem::path & hsgr_path) {
|
||||||
|
typename ShM<typename QueryGraph::_StrNode, false>::vector node_list;
|
||||||
|
typename ShM<typename QueryGraph::_StrEdge, false>::vector edge_list;
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "loading graph from " << hsgr_path.string();
|
||||||
|
|
||||||
|
m_number_of_nodes = readHSGRFromStream(
|
||||||
|
hsgr_path,
|
||||||
|
node_list,
|
||||||
|
edge_list,
|
||||||
|
&m_check_sum
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty");
|
||||||
|
BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty");
|
||||||
|
SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges";
|
||||||
|
m_query_graph = new QueryGraph(node_list, edge_list);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(0 == node_list.size(), "node list not flushed");
|
||||||
|
BOOST_ASSERT_MSG(0 == edge_list.size(), "edge list not flushed");
|
||||||
|
SimpleLogger().Write() << "Data checksum is " << m_check_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadNodeAndEdgeInformation(
|
||||||
|
const boost::filesystem::path nodes_file,
|
||||||
|
const boost::filesystem::path edges_file
|
||||||
|
) {
|
||||||
|
boost::filesystem::ifstream nodes_input_stream(
|
||||||
|
nodes_file,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Loading node data";
|
||||||
|
NodeInfo current_node;
|
||||||
|
unsigned number_of_coordinates = 0;
|
||||||
|
nodes_input_stream.read(
|
||||||
|
(char *)&number_of_coordinates,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
m_coordinate_list.resize(number_of_coordinates);
|
||||||
|
for(unsigned i = 0; i < number_of_coordinates; ++i) {
|
||||||
|
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||||
|
m_coordinate_list[i] = FixedPointCoordinate(
|
||||||
|
current_node.lat,
|
||||||
|
current_node.lon
|
||||||
|
);
|
||||||
|
}
|
||||||
|
std::vector<FixedPointCoordinate>(m_coordinate_list).swap(m_coordinate_list);
|
||||||
|
nodes_input_stream.close();
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Loading edge data";
|
||||||
|
boost::filesystem::ifstream edges_input_stream(
|
||||||
|
edges_file,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
unsigned number_of_edges = 0;
|
||||||
|
edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned));
|
||||||
|
m_via_node_list.resize(number_of_edges);
|
||||||
|
m_name_ID_list.resize(number_of_edges);
|
||||||
|
m_turn_instruction_list.resize(number_of_edges);
|
||||||
|
|
||||||
|
OriginalEdgeData current_edge_data;
|
||||||
|
for(unsigned i = 0; i < number_of_edges; ++i) {
|
||||||
|
edges_input_stream.read(
|
||||||
|
(char*)&(current_edge_data),
|
||||||
|
sizeof(OriginalEdgeData)
|
||||||
|
);
|
||||||
|
m_via_node_list[i] = current_edge_data.viaNode;
|
||||||
|
m_name_ID_list[i] = current_edge_data.nameID;
|
||||||
|
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
|
||||||
|
}
|
||||||
|
edges_input_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadRTree(
|
||||||
|
const boost::filesystem::path & ram_index_path,
|
||||||
|
const boost::filesystem::path & file_index_path
|
||||||
|
) {
|
||||||
|
m_static_rtree = new StaticRTree<RTreeLeaf>(
|
||||||
|
ram_index_path,
|
||||||
|
file_index_path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadStreetNames(
|
||||||
|
const boost::filesystem::path & names_file
|
||||||
|
) {
|
||||||
|
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
|
||||||
|
unsigned number_of_names = 0;
|
||||||
|
unsigned number_of_chars = 0;
|
||||||
|
name_stream.read((char *)&number_of_names, sizeof(unsigned));
|
||||||
|
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||||
|
BOOST_ASSERT_MSG(0 != number_of_names, "name file broken");
|
||||||
|
BOOST_ASSERT_MSG(0 != number_of_chars, "name file broken");
|
||||||
|
|
||||||
|
m_name_begin_indices.resize(number_of_names);
|
||||||
|
name_stream.read(
|
||||||
|
(char*)&m_name_begin_indices[0],
|
||||||
|
number_of_names*sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
m_names_char_list.resize(number_of_chars+1); //+1 gives sentinel element
|
||||||
|
name_stream.read(
|
||||||
|
(char *)&m_names_char_list[0],
|
||||||
|
number_of_chars*sizeof(char)
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 != m_names_char_list.size(),
|
||||||
|
"could not load any names"
|
||||||
|
);
|
||||||
|
name_stream.close();
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
~InternalDataFacade() {
|
||||||
|
delete m_query_graph;
|
||||||
|
delete m_static_rtree;
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalDataFacade( const ServerPaths & server_paths ) {
|
||||||
|
//generate paths of data files
|
||||||
|
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no hsgr file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("ramindex") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no ram index file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no leaf index file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no nodes file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("edgesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no edges file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("namesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no names file given in ini file");
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & hsgr_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("timestamp");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & timestamp_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("ramindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & ram_index_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("fileindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & file_index_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("nodesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & nodes_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("edgesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & edges_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("namesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
||||||
|
|
||||||
|
//load data
|
||||||
|
SimpleLogger().Write() << "loading graph data";
|
||||||
|
LoadGraph(hsgr_path);
|
||||||
|
SimpleLogger().Write() << "loading egde information";
|
||||||
|
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
||||||
|
SimpleLogger().Write() << "loading r-tree";
|
||||||
|
LoadRTree(ram_index_path, file_index_path);
|
||||||
|
SimpleLogger().Write() << "loading timestamp";
|
||||||
|
LoadTimestamp(timestamp_path);
|
||||||
|
SimpleLogger().Write() << "loading street names";
|
||||||
|
LoadStreetNames(names_data_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
//search graph access
|
||||||
|
unsigned GetNumberOfNodes() const {
|
||||||
|
return m_query_graph->GetNumberOfNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetNumberOfEdges() const {
|
||||||
|
return m_query_graph->GetNumberOfEdges();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetOutDegree( const NodeID n ) const {
|
||||||
|
return m_query_graph->GetOutDegree(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID GetTarget( const EdgeID e ) const {
|
||||||
|
return m_query_graph->GetTarget(e); }
|
||||||
|
|
||||||
|
EdgeDataT &GetEdgeData( const EdgeID e ) {
|
||||||
|
return m_query_graph->GetEdgeData(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EdgeDataT &GetEdgeData( const EdgeID e ) const {
|
||||||
|
return m_query_graph->GetEdgeData(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID BeginEdges( const NodeID n ) const {
|
||||||
|
return m_query_graph->BeginEdges(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID EndEdges( const NodeID n ) const {
|
||||||
|
return m_query_graph->EndEdges(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
//searches for a specific edge
|
||||||
|
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
|
||||||
|
return m_query_graph->FindEdge(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID FindEdgeInEitherDirection(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to
|
||||||
|
) const {
|
||||||
|
return m_query_graph->FindEdgeInEitherDirection(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID FindEdgeIndicateIfReverse(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to,
|
||||||
|
bool & result
|
||||||
|
) const {
|
||||||
|
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//node and edge information access
|
||||||
|
FixedPointCoordinate GetCoordinateOfNode(
|
||||||
|
const unsigned id
|
||||||
|
) const {
|
||||||
|
const NodeID node = m_via_node_list.at(id);
|
||||||
|
return m_coordinate_list.at(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
|
const unsigned id
|
||||||
|
) const {
|
||||||
|
return m_turn_instruction_list.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocateClosestEndPointForCoordinate(
|
||||||
|
const FixedPointCoordinate& input_coordinate,
|
||||||
|
FixedPointCoordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const {
|
||||||
|
return m_static_rtree->LocateClosestEndPointForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
result,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) const {
|
||||||
|
return m_static_rtree->FindPhantomNodeForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
resulting_phantom_node,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetCheckSum() const { return m_check_sum; }
|
||||||
|
|
||||||
|
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
|
||||||
|
return m_name_ID_list.at(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
void GetName( const unsigned name_id, std::string & result ) const {
|
||||||
|
if(UINT_MAX == name_id) {
|
||||||
|
result = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
name_id < m_name_begin_indices.size(),
|
||||||
|
"name id too high"
|
||||||
|
);
|
||||||
|
unsigned begin_index = m_name_begin_indices[name_id];
|
||||||
|
unsigned end_index = m_name_begin_indices[name_id+1];
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
begin_index < m_names_char_list.size(),
|
||||||
|
"begin index of name too high"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
end_index < m_names_char_list.size(),
|
||||||
|
"end index of name too high"
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
|
||||||
|
result.clear();
|
||||||
|
result.resize(end_index - begin_index);
|
||||||
|
std::copy(
|
||||||
|
m_names_char_list.begin() + begin_index,
|
||||||
|
m_names_char_list.begin() + end_index,
|
||||||
|
result.begin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetTimestamp() const {
|
||||||
|
return m_timestamp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INTERNAL_DATA_FACADE
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
|
||||||
of conditions and the following disclaimer.
|
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "QueryObjectsStorage.h"
|
|
||||||
|
|
||||||
QueryObjectsStorage::QueryObjectsStorage( const ServerPaths & paths ) {
|
|
||||||
if( paths.find("hsgrdata") == paths.end() ) {
|
|
||||||
throw OSRMException("no hsgr file given in ini file");
|
|
||||||
}
|
|
||||||
if( paths.find("ramindex") == paths.end() ) {
|
|
||||||
throw OSRMException("no ram index file given in ini file");
|
|
||||||
}
|
|
||||||
if( paths.find("fileindex") == paths.end() ) {
|
|
||||||
throw OSRMException("no mem index file given in ini file");
|
|
||||||
}
|
|
||||||
if( paths.find("nodesdata") == paths.end() ) {
|
|
||||||
throw OSRMException("no nodes file given in ini file");
|
|
||||||
}
|
|
||||||
if( paths.find("edgesdata") == paths.end() ) {
|
|
||||||
throw OSRMException("no edges file given in ini file");
|
|
||||||
}
|
|
||||||
if( paths.find("namesdata") == paths.end() ) {
|
|
||||||
throw OSRMException("no names file given in ini file");
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "loading graph data";
|
|
||||||
//Deserialize road network graph
|
|
||||||
|
|
||||||
ServerPaths::const_iterator paths_iterator = paths.find("hsgrdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
const std::string & hsgr_data_string = paths_iterator->second.string();
|
|
||||||
|
|
||||||
std::vector< QueryGraph::_StrNode> node_list;
|
|
||||||
std::vector< QueryGraph::_StrEdge> edge_list;
|
|
||||||
const int number_of_nodes = readHSGRFromStream(
|
|
||||||
hsgr_data_string,
|
|
||||||
node_list,
|
|
||||||
edge_list,
|
|
||||||
&check_sum
|
|
||||||
);
|
|
||||||
|
|
||||||
SimpleLogger().Write() << "Data checksum is " << check_sum;
|
|
||||||
graph = new QueryGraph(node_list, edge_list);
|
|
||||||
BOOST_ASSERT(0 == node_list.size());
|
|
||||||
BOOST_ASSERT(0 == edge_list.size());
|
|
||||||
|
|
||||||
paths_iterator = paths.find("timestamp");
|
|
||||||
|
|
||||||
if(paths.end() != paths_iterator) {
|
|
||||||
SimpleLogger().Write() << "Loading Timestamp";
|
|
||||||
const std::string & timestamp_string = paths_iterator->second.string();
|
|
||||||
|
|
||||||
boost::filesystem::ifstream time_stamp_instream(timestamp_string);
|
|
||||||
if( !time_stamp_instream.good() ) {
|
|
||||||
SimpleLogger().Write(logWARNING) << timestamp_string << " not found";
|
|
||||||
}
|
|
||||||
|
|
||||||
getline(time_stamp_instream, timestamp);
|
|
||||||
time_stamp_instream.close();
|
|
||||||
}
|
|
||||||
if(!timestamp.length()) {
|
|
||||||
timestamp = "n/a";
|
|
||||||
}
|
|
||||||
if(25 < timestamp.length()) {
|
|
||||||
timestamp.resize(25);
|
|
||||||
}
|
|
||||||
SimpleLogger().Write() << "Loading auxiliary information";
|
|
||||||
|
|
||||||
paths_iterator = paths.find("ramindex");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
const std::string & ram_index_string = paths_iterator->second.string();
|
|
||||||
paths_iterator = paths.find("fileindex");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
const std::string & file_index_string = paths_iterator->second.string();
|
|
||||||
paths_iterator = paths.find("nodesdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
const std::string & nodes_data_string = paths_iterator->second.string();
|
|
||||||
paths_iterator = paths.find("edgesdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
const std::string & edges_data_string = paths_iterator->second.string();
|
|
||||||
|
|
||||||
//Init nearest neighbor data structure
|
|
||||||
nodeHelpDesk = new NodeInformationHelpDesk(
|
|
||||||
ram_index_string,
|
|
||||||
file_index_string,
|
|
||||||
nodes_data_string,
|
|
||||||
edges_data_string,
|
|
||||||
number_of_nodes,
|
|
||||||
check_sum
|
|
||||||
);
|
|
||||||
|
|
||||||
//deserialize street name list
|
|
||||||
SimpleLogger().Write() << "Loading names index";
|
|
||||||
|
|
||||||
paths_iterator = paths.find("namesdata");
|
|
||||||
BOOST_ASSERT(paths.end() != paths_iterator);
|
|
||||||
const std::string & names_data_string = paths_iterator->second.string();
|
|
||||||
if ( !boost::filesystem::exists( paths_iterator->second ) ) {
|
|
||||||
throw OSRMException("names file does not exist");
|
|
||||||
}
|
|
||||||
if ( 0 == boost::filesystem::file_size( paths_iterator->second ) ) {
|
|
||||||
throw OSRMException("names file is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::filesystem::ifstream name_stream(names_data_string, std::ios::binary);
|
|
||||||
unsigned size = 0;
|
|
||||||
name_stream.read((char *)&size, sizeof(unsigned));
|
|
||||||
BOOST_ASSERT_MSG(0 != size, "name file broken");
|
|
||||||
|
|
||||||
m_name_begin_indices.resize(size);
|
|
||||||
name_stream.read((char*)&m_name_begin_indices[0], size*sizeof(unsigned));
|
|
||||||
name_stream.read((char *)&size, sizeof(unsigned));
|
|
||||||
BOOST_ASSERT_MSG(0 != size, "name file broken");
|
|
||||||
|
|
||||||
m_names_char_list.resize(size+1); //+1 is sentinel/dummy element
|
|
||||||
name_stream.read((char *)&m_names_char_list[0], size*sizeof(char));
|
|
||||||
BOOST_ASSERT_MSG(0 != m_names_char_list.size(), "could not load any names");
|
|
||||||
|
|
||||||
name_stream.close();
|
|
||||||
SimpleLogger().Write() << "All query data structures loaded";
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueryObjectsStorage::GetName(
|
|
||||||
const unsigned name_id,
|
|
||||||
std::string & result
|
|
||||||
) const {
|
|
||||||
if(UINT_MAX == name_id) {
|
|
||||||
result = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
name_id < m_name_begin_indices.size(),
|
|
||||||
"name id too high"
|
|
||||||
);
|
|
||||||
unsigned begin_index = m_name_begin_indices[name_id];
|
|
||||||
unsigned end_index = m_name_begin_indices[name_id+1];
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
begin_index < m_names_char_list.size(),
|
|
||||||
"begin index of name too high"
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG(
|
|
||||||
end_index < m_names_char_list.size(),
|
|
||||||
"end index of name too high"
|
|
||||||
);
|
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
|
|
||||||
result.clear();
|
|
||||||
result.resize(end_index - begin_index);
|
|
||||||
std::copy(
|
|
||||||
m_names_char_list.begin() + begin_index,
|
|
||||||
m_names_char_list.begin() + end_index,
|
|
||||||
result.begin()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryObjectsStorage::~QueryObjectsStorage() {
|
|
||||||
delete graph;
|
|
||||||
delete nodeHelpDesk;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include <boost/interprocess/sync/named_mutex.hpp>
|
||||||
|
#include <boost/interprocess/sync/named_condition.hpp>
|
||||||
|
|
||||||
|
struct SharedBarriers {
|
||||||
|
|
||||||
|
SharedBarriers ()
|
||||||
|
:
|
||||||
|
pending_update_mutex(
|
||||||
|
boost::interprocess::open_or_create,
|
||||||
|
"pending_update"
|
||||||
|
),
|
||||||
|
update_mutex(
|
||||||
|
boost::interprocess::open_or_create,
|
||||||
|
"update"
|
||||||
|
),
|
||||||
|
query_mutex(
|
||||||
|
boost::interprocess::open_or_create,
|
||||||
|
"query"
|
||||||
|
),
|
||||||
|
no_running_queries_condition(
|
||||||
|
boost::interprocess::open_or_create,
|
||||||
|
"no_running_queries"
|
||||||
|
),
|
||||||
|
update_ongoing(false),
|
||||||
|
number_of_queries(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
// Mutex to protect access to the boolean variable
|
||||||
|
boost::interprocess::named_mutex pending_update_mutex;
|
||||||
|
boost::interprocess::named_mutex update_mutex;
|
||||||
|
boost::interprocess::named_mutex query_mutex;
|
||||||
|
|
||||||
|
// Condition that no update is running
|
||||||
|
boost::interprocess::named_condition no_running_queries_condition;
|
||||||
|
|
||||||
|
// Is there an ongoing update?
|
||||||
|
bool update_ongoing;
|
||||||
|
// Is there any query?
|
||||||
|
int number_of_queries;
|
||||||
|
};
|
||||||
@@ -0,0 +1,385 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARED_DATA_FACADE_H
|
||||||
|
#define SHARED_DATA_FACADE_H
|
||||||
|
|
||||||
|
//implements all data storage when shared memory is _NOT_ used
|
||||||
|
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include "BaseDataFacade.h"
|
||||||
|
#include "SharedDataType.h"
|
||||||
|
|
||||||
|
#include "../../DataStructures/StaticGraph.h"
|
||||||
|
#include "../../DataStructures/StaticRTree.h"
|
||||||
|
#include "../../Util/BoostFileSystemFix.h"
|
||||||
|
#include "../../Util/ProgramOptions.h"
|
||||||
|
#include "../../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template<class EdgeDataT>
|
||||||
|
class SharedDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef EdgeDataT EdgeData;
|
||||||
|
typedef BaseDataFacade<EdgeData> super;
|
||||||
|
typedef StaticGraph<EdgeData, true> QueryGraph;
|
||||||
|
typedef typename StaticGraph<EdgeData, true>::_StrNode GraphNode;
|
||||||
|
typedef typename StaticGraph<EdgeData, true>::_StrEdge GraphEdge;
|
||||||
|
typedef typename QueryGraph::InputEdge InputEdge;
|
||||||
|
typedef typename super::RTreeLeaf RTreeLeaf;
|
||||||
|
typedef typename StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
|
||||||
|
|
||||||
|
SharedDataLayout * data_layout;
|
||||||
|
char * shared_memory;
|
||||||
|
SharedDataTimestamp * data_timestamp_ptr;
|
||||||
|
|
||||||
|
SharedDataType CURRENT_LAYOUT;
|
||||||
|
SharedDataType CURRENT_DATA;
|
||||||
|
unsigned CURRENT_TIMESTAMP;
|
||||||
|
|
||||||
|
unsigned m_check_sum;
|
||||||
|
unsigned m_number_of_nodes;
|
||||||
|
boost::shared_ptr<QueryGraph> m_query_graph;
|
||||||
|
boost::shared_ptr<SharedMemory> m_layout_memory;
|
||||||
|
boost::shared_ptr<SharedMemory> m_large_memory;
|
||||||
|
std::string m_timestamp;
|
||||||
|
|
||||||
|
ShM<FixedPointCoordinate, true>::vector m_coordinate_list;
|
||||||
|
ShM<NodeID, true>::vector m_via_node_list;
|
||||||
|
ShM<unsigned, true>::vector m_name_ID_list;
|
||||||
|
ShM<TurnInstruction, true>::vector m_turn_instruction_list;
|
||||||
|
ShM<char, true>::vector m_names_char_list;
|
||||||
|
ShM<unsigned, true>::vector m_name_begin_indices;
|
||||||
|
boost::shared_ptr<StaticRTree<RTreeLeaf, true> > m_static_rtree;
|
||||||
|
|
||||||
|
// SharedDataFacade() { }
|
||||||
|
|
||||||
|
void LoadTimestamp() {
|
||||||
|
char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset();
|
||||||
|
m_timestamp.resize(data_layout->timestamp_length);
|
||||||
|
std::copy(
|
||||||
|
timestamp_ptr,
|
||||||
|
timestamp_ptr+data_layout->timestamp_length,
|
||||||
|
m_timestamp.begin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadRTree(
|
||||||
|
const boost::filesystem::path & file_index_path
|
||||||
|
) {
|
||||||
|
RTreeNode * tree_ptr = (RTreeNode *)(
|
||||||
|
shared_memory + data_layout->GetRSearchTreeOffset()
|
||||||
|
);
|
||||||
|
m_static_rtree = boost::make_shared<StaticRTree<RTreeLeaf, true> >(
|
||||||
|
tree_ptr,
|
||||||
|
data_layout->r_search_tree_size,
|
||||||
|
file_index_path
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadGraph() {
|
||||||
|
m_number_of_nodes = data_layout->graph_node_list_size;
|
||||||
|
GraphNode * graph_nodes_ptr = (GraphNode *)(
|
||||||
|
shared_memory + data_layout->GetGraphNodeListOffset()
|
||||||
|
);
|
||||||
|
|
||||||
|
GraphEdge * graph_edges_ptr = (GraphEdge *)(
|
||||||
|
shared_memory + data_layout->GetGraphEdgeListOffsett()
|
||||||
|
);
|
||||||
|
|
||||||
|
typename ShM<GraphNode, true>::vector node_list(
|
||||||
|
graph_nodes_ptr,
|
||||||
|
data_layout->graph_node_list_size
|
||||||
|
);
|
||||||
|
typename ShM<GraphEdge, true>::vector edge_list(
|
||||||
|
graph_edges_ptr,
|
||||||
|
data_layout->graph_edge_list_size
|
||||||
|
);
|
||||||
|
m_query_graph.reset(
|
||||||
|
new QueryGraph(node_list, edge_list)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadNodeAndEdgeInformation() {
|
||||||
|
|
||||||
|
FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)(
|
||||||
|
shared_memory + data_layout->GetCoordinateListOffset()
|
||||||
|
);
|
||||||
|
typename ShM<FixedPointCoordinate, true>::vector coordinate_list(
|
||||||
|
coordinate_list_ptr,
|
||||||
|
data_layout->coordinate_list_size
|
||||||
|
);
|
||||||
|
m_coordinate_list.swap( coordinate_list );
|
||||||
|
|
||||||
|
TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)(
|
||||||
|
shared_memory + data_layout->GetTurnInstructionListOffset()
|
||||||
|
);
|
||||||
|
typename ShM<TurnInstruction, true>::vector turn_instruction_list(
|
||||||
|
turn_instruction_list_ptr,
|
||||||
|
data_layout->turn_instruction_list_size
|
||||||
|
);
|
||||||
|
m_turn_instruction_list.swap(turn_instruction_list);
|
||||||
|
|
||||||
|
unsigned * name_id_list_ptr = (unsigned *)(
|
||||||
|
shared_memory + data_layout->GetNameIDListOffset()
|
||||||
|
);
|
||||||
|
typename ShM<unsigned, true>::vector name_id_list(
|
||||||
|
name_id_list_ptr,
|
||||||
|
data_layout->name_id_list_size
|
||||||
|
);
|
||||||
|
m_name_ID_list.swap(name_id_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadViaNodeList() {
|
||||||
|
NodeID * via_node_list_ptr = (NodeID *)(
|
||||||
|
shared_memory + data_layout->GetViaNodeListOffset()
|
||||||
|
);
|
||||||
|
typename ShM<NodeID, true>::vector via_node_list(
|
||||||
|
via_node_list_ptr,
|
||||||
|
data_layout->via_node_list_size
|
||||||
|
);
|
||||||
|
m_via_node_list.swap(via_node_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadNames() {
|
||||||
|
unsigned * street_names_index_ptr = (unsigned *)(
|
||||||
|
shared_memory + data_layout->GetNameIndexOffset()
|
||||||
|
);
|
||||||
|
typename ShM<unsigned, true>::vector name_begin_indices(
|
||||||
|
street_names_index_ptr,
|
||||||
|
data_layout->name_index_list_size
|
||||||
|
);
|
||||||
|
m_name_begin_indices.swap(name_begin_indices);
|
||||||
|
|
||||||
|
char * names_list_ptr = (char *)(
|
||||||
|
shared_memory + data_layout->GetNameListOffset()
|
||||||
|
);
|
||||||
|
typename ShM<char, true>::vector names_char_list(
|
||||||
|
names_list_ptr,
|
||||||
|
data_layout->name_char_list_size
|
||||||
|
);
|
||||||
|
m_names_char_list.swap(names_char_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SharedDataFacade( ) {
|
||||||
|
data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get(
|
||||||
|
CURRENT_REGIONS,
|
||||||
|
sizeof(SharedDataTimestamp),
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
)->Ptr();
|
||||||
|
|
||||||
|
CURRENT_LAYOUT = LAYOUT_NONE;
|
||||||
|
CURRENT_DATA = DATA_NONE;
|
||||||
|
CURRENT_TIMESTAMP = 0;
|
||||||
|
|
||||||
|
//load data
|
||||||
|
CheckAndReloadFacade();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckAndReloadFacade() {
|
||||||
|
if(
|
||||||
|
CURRENT_LAYOUT != data_timestamp_ptr->layout ||
|
||||||
|
CURRENT_DATA != data_timestamp_ptr->data ||
|
||||||
|
CURRENT_TIMESTAMP != data_timestamp_ptr->timestamp
|
||||||
|
) {
|
||||||
|
// release the previous shared memory segments
|
||||||
|
SharedMemory::Remove(CURRENT_LAYOUT);
|
||||||
|
SharedMemory::Remove(CURRENT_DATA);
|
||||||
|
|
||||||
|
CURRENT_LAYOUT = data_timestamp_ptr->layout;
|
||||||
|
CURRENT_DATA = data_timestamp_ptr->data;
|
||||||
|
CURRENT_TIMESTAMP = data_timestamp_ptr->timestamp;
|
||||||
|
|
||||||
|
m_layout_memory.reset( SharedMemoryFactory::Get(CURRENT_LAYOUT) );
|
||||||
|
|
||||||
|
data_layout = (SharedDataLayout *)(
|
||||||
|
m_layout_memory->Ptr()
|
||||||
|
);
|
||||||
|
boost::filesystem::path ram_index_path(data_layout->ram_index_file_name);
|
||||||
|
if( !boost::filesystem::exists(ram_index_path) ) {
|
||||||
|
throw OSRMException(
|
||||||
|
"no leaf index file given. "
|
||||||
|
"Is any data loaded into shared memory?"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_large_memory.reset( SharedMemoryFactory::Get(CURRENT_DATA) );
|
||||||
|
shared_memory = (char *)(
|
||||||
|
m_large_memory->Ptr()
|
||||||
|
);
|
||||||
|
|
||||||
|
LoadGraph();
|
||||||
|
LoadNodeAndEdgeInformation();
|
||||||
|
LoadRTree(ram_index_path);
|
||||||
|
LoadTimestamp();
|
||||||
|
LoadViaNodeList();
|
||||||
|
LoadNames();
|
||||||
|
|
||||||
|
data_layout->PrintInformation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//search graph access
|
||||||
|
unsigned GetNumberOfNodes() const {
|
||||||
|
return m_query_graph->GetNumberOfNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetNumberOfEdges() const {
|
||||||
|
return m_query_graph->GetNumberOfEdges();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetOutDegree( const NodeID n ) const {
|
||||||
|
return m_query_graph->GetOutDegree(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID GetTarget( const EdgeID e ) const {
|
||||||
|
return m_query_graph->GetTarget(e); }
|
||||||
|
|
||||||
|
EdgeDataT &GetEdgeData( const EdgeID e ) {
|
||||||
|
return m_query_graph->GetEdgeData(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// const EdgeDataT &GetEdgeData( const EdgeID e ) const {
|
||||||
|
// return m_query_graph->GetEdgeData(e);
|
||||||
|
// }
|
||||||
|
|
||||||
|
EdgeID BeginEdges( const NodeID n ) const {
|
||||||
|
return m_query_graph->BeginEdges(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID EndEdges( const NodeID n ) const {
|
||||||
|
return m_query_graph->EndEdges(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
//searches for a specific edge
|
||||||
|
EdgeID FindEdge( const NodeID from, const NodeID to ) const {
|
||||||
|
return m_query_graph->FindEdge(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID FindEdgeInEitherDirection(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to
|
||||||
|
) const {
|
||||||
|
return m_query_graph->FindEdgeInEitherDirection(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeID FindEdgeIndicateIfReverse(
|
||||||
|
const NodeID from,
|
||||||
|
const NodeID to,
|
||||||
|
bool & result
|
||||||
|
) const {
|
||||||
|
return m_query_graph->FindEdgeIndicateIfReverse(from, to, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
//node and edge information access
|
||||||
|
FixedPointCoordinate GetCoordinateOfNode(
|
||||||
|
const unsigned id
|
||||||
|
) const {
|
||||||
|
const NodeID node = m_via_node_list.at(id);
|
||||||
|
return m_coordinate_list.at(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
TurnInstruction GetTurnInstructionForEdgeID(
|
||||||
|
const unsigned id
|
||||||
|
) const {
|
||||||
|
return m_turn_instruction_list.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LocateClosestEndPointForCoordinate(
|
||||||
|
const FixedPointCoordinate& input_coordinate,
|
||||||
|
FixedPointCoordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const {
|
||||||
|
return m_static_rtree->LocateClosestEndPointForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
result,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) const {
|
||||||
|
return m_static_rtree->FindPhantomNodeForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
resulting_phantom_node,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned GetCheckSum() const { return m_check_sum; }
|
||||||
|
|
||||||
|
unsigned GetNameIndexFromEdgeID(const unsigned id) const {
|
||||||
|
return m_name_ID_list.at(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
void GetName( const unsigned name_id, std::string & result ) const {
|
||||||
|
if(UINT_MAX == name_id) {
|
||||||
|
result = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
name_id < m_name_begin_indices.size(),
|
||||||
|
"name id too high"
|
||||||
|
);
|
||||||
|
unsigned begin_index = m_name_begin_indices[name_id];
|
||||||
|
unsigned end_index = m_name_begin_indices[name_id+1];
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
begin_index < m_names_char_list.size(),
|
||||||
|
"begin index of name too high"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
end_index < m_names_char_list.size(),
|
||||||
|
"end index of name too high"
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(begin_index <= end_index, "string ends before begin");
|
||||||
|
result.clear();
|
||||||
|
result.resize(end_index - begin_index);
|
||||||
|
std::copy(
|
||||||
|
m_names_char_list.begin() + begin_index,
|
||||||
|
m_names_char_list.begin() + end_index,
|
||||||
|
result.begin()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetTimestamp() const {
|
||||||
|
return m_timestamp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARED_DATA_FACADE_H
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SHARED_DATA_TYPE_H_
|
||||||
|
#define SHARED_DATA_TYPE_H_
|
||||||
|
|
||||||
|
#include "BaseDataFacade.h"
|
||||||
|
|
||||||
|
#include "../../DataStructures/Coordinate.h"
|
||||||
|
#include "../../DataStructures/QueryEdge.h"
|
||||||
|
#include "../../DataStructures/StaticGraph.h"
|
||||||
|
#include "../../DataStructures/StaticRTree.h"
|
||||||
|
#include "../../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
|
#include "../../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
|
||||||
|
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
|
||||||
|
typedef StaticRTree<RTreeLeaf, true>::TreeNode RTreeNode;
|
||||||
|
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
|
|
||||||
|
struct SharedDataLayout {
|
||||||
|
uint64_t name_index_list_size;
|
||||||
|
uint64_t name_char_list_size;
|
||||||
|
uint64_t name_id_list_size;
|
||||||
|
uint64_t via_node_list_size;
|
||||||
|
uint64_t graph_node_list_size;
|
||||||
|
uint64_t graph_edge_list_size;
|
||||||
|
uint64_t coordinate_list_size;
|
||||||
|
uint64_t turn_instruction_list_size;
|
||||||
|
uint64_t r_search_tree_size;
|
||||||
|
|
||||||
|
unsigned checksum;
|
||||||
|
unsigned timestamp_length;
|
||||||
|
|
||||||
|
char ram_index_file_name[1024];
|
||||||
|
|
||||||
|
SharedDataLayout() :
|
||||||
|
name_index_list_size(0),
|
||||||
|
name_char_list_size(0),
|
||||||
|
name_id_list_size(0),
|
||||||
|
via_node_list_size(0),
|
||||||
|
graph_node_list_size(0),
|
||||||
|
graph_edge_list_size(0),
|
||||||
|
coordinate_list_size(0),
|
||||||
|
turn_instruction_list_size(0),
|
||||||
|
r_search_tree_size(0),
|
||||||
|
checksum(0),
|
||||||
|
timestamp_length(0)
|
||||||
|
{
|
||||||
|
ram_index_file_name[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintInformation() const {
|
||||||
|
SimpleLogger().Write(logDEBUG) << "-";
|
||||||
|
SimpleLogger().Write(logDEBUG) << "name_index_list_size: " << name_index_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "name_char_list_size: " << name_char_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "name_id_list_size: " << name_id_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "via_node_list_size: " << via_node_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "graph_node_list_size: " << graph_node_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "graph_edge_list_size: " << graph_edge_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "timestamp_length: " << timestamp_length;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << coordinate_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_list_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << r_search_tree_size;
|
||||||
|
SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << sizeof(checksum);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GetSizeOfLayout() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||||
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||||
|
(timestamp_length * sizeof(char) ) +
|
||||||
|
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
||||||
|
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
|
||||||
|
(r_search_tree_size * sizeof(RTreeNode) ) +
|
||||||
|
sizeof(checksum) +
|
||||||
|
1024*sizeof(char);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GetNameIndexOffset() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint64_t GetNameListOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetNameIDListOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetViaNodeListOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetGraphNodeListOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetGraphEdgeListOffsett() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) ;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetTimeStampOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||||
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetCoordinateListOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||||
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||||
|
(timestamp_length * sizeof(char) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetTurnInstructionListOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||||
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||||
|
(timestamp_length * sizeof(char) ) +
|
||||||
|
(coordinate_list_size * sizeof(FixedPointCoordinate));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetRSearchTreeOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||||
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||||
|
(timestamp_length * sizeof(char) ) +
|
||||||
|
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
||||||
|
(turn_instruction_list_size * sizeof(TurnInstructions) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
uint64_t GetChecksumOffset() const {
|
||||||
|
uint64_t result =
|
||||||
|
(name_index_list_size * sizeof(unsigned) ) +
|
||||||
|
(name_char_list_size * sizeof(char) ) +
|
||||||
|
(name_id_list_size * sizeof(unsigned) ) +
|
||||||
|
(via_node_list_size * sizeof(NodeID) ) +
|
||||||
|
(graph_node_list_size * sizeof(QueryGraph::_StrNode)) +
|
||||||
|
(graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) +
|
||||||
|
(timestamp_length * sizeof(char) ) +
|
||||||
|
(coordinate_list_size * sizeof(FixedPointCoordinate)) +
|
||||||
|
(turn_instruction_list_size * sizeof(TurnInstructions) ) +
|
||||||
|
(r_search_tree_size * sizeof(RTreeNode) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SharedDataType {
|
||||||
|
CURRENT_REGIONS,
|
||||||
|
LAYOUT_1,
|
||||||
|
DATA_1,
|
||||||
|
LAYOUT_2,
|
||||||
|
DATA_2,
|
||||||
|
LAYOUT_NONE,
|
||||||
|
DATA_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SharedDataTimestamp {
|
||||||
|
SharedDataType layout;
|
||||||
|
SharedDataType data;
|
||||||
|
unsigned timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SHARED_DATA_TYPE_H_ */
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 BASIC_DATASTRUCTURES_H
|
||||||
|
#define BASIC_DATASTRUCTURES_H
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
enum CompressionType {
|
||||||
|
noCompression,
|
||||||
|
gzipRFC1952,
|
||||||
|
deflateRFC1951
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
|
|
||||||
|
#endif //BASIC_DATASTRUCTURES_H
|
||||||
@@ -25,33 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BRESENHAM_H_
|
#ifndef HTTP_HEADER_H
|
||||||
#define BRESENHAM_H_
|
#define HTTP_HEADER_H
|
||||||
|
|
||||||
#include <cmath>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
typedef std::pair<unsigned, unsigned> BresenhamPixel;
|
namespace http {
|
||||||
|
|
||||||
inline void Bresenham (int x0, int y0, const int x1, int const y1, std::vector<BresenhamPixel> &resultList) {
|
struct Header {
|
||||||
int dx = std::abs(x1-x0);
|
std::string name;
|
||||||
int dy = std::abs(y1-y0);
|
std::string value;
|
||||||
int sx = (x0 < x1 ? 1 : -1);
|
void Clear() {
|
||||||
int sy = (y0 < y1 ? 1 : -1);
|
name.clear();
|
||||||
int err = dx - dy;
|
value.clear();
|
||||||
while(true) {
|
|
||||||
resultList.push_back(std::make_pair(x0,y0));
|
|
||||||
if(x0 == x1 && y0 == y1) break;
|
|
||||||
int e2 = 2* err;
|
|
||||||
if ( e2 > -dy) {
|
|
||||||
err -= dy;
|
|
||||||
x0 += sx;
|
|
||||||
}
|
}
|
||||||
if(e2 < dx) {
|
};
|
||||||
err+= dx;
|
|
||||||
y0 += sy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* BRESENHAM_H_ */
|
#endif //HTTP_HEADER_H
|
||||||
|
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "Reply.h"
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
void Reply::setSize(const unsigned size) {
|
||||||
|
BOOST_FOREACH ( Header& h, headers) {
|
||||||
|
if("Content-Length" == h.name) {
|
||||||
|
std::string sizeString;
|
||||||
|
intToString(size,h.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
|
||||||
|
std::vector<boost::asio::const_buffer> buffers;
|
||||||
|
buffers.push_back(ToBuffer(status));
|
||||||
|
BOOST_FOREACH(const Header & h, headers) {
|
||||||
|
buffers.push_back(boost::asio::buffer(h.name));
|
||||||
|
buffers.push_back(boost::asio::buffer(seperators));
|
||||||
|
buffers.push_back(boost::asio::buffer(h.value));
|
||||||
|
buffers.push_back(boost::asio::buffer(crlf));
|
||||||
|
}
|
||||||
|
buffers.push_back(boost::asio::buffer(crlf));
|
||||||
|
BOOST_FOREACH(const std::string & line, content) {
|
||||||
|
buffers.push_back(boost::asio::buffer(line));
|
||||||
|
}
|
||||||
|
return buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<boost::asio::const_buffer> Reply::HeaderstoBuffers(){
|
||||||
|
std::vector<boost::asio::const_buffer> buffers;
|
||||||
|
buffers.push_back(ToBuffer(status));
|
||||||
|
for (std::size_t i = 0; i < headers.size(); ++i) {
|
||||||
|
Header& h = headers[i];
|
||||||
|
buffers.push_back(boost::asio::buffer(h.name));
|
||||||
|
buffers.push_back(boost::asio::buffer(seperators));
|
||||||
|
buffers.push_back(boost::asio::buffer(h.value));
|
||||||
|
buffers.push_back(boost::asio::buffer(crlf));
|
||||||
|
}
|
||||||
|
buffers.push_back(boost::asio::buffer(crlf));
|
||||||
|
return buffers;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reply Reply::StockReply(Reply::status_type status) {
|
||||||
|
Reply rep;
|
||||||
|
rep.status = status;
|
||||||
|
rep.content.clear();
|
||||||
|
rep.content.push_back( ToString(status) );
|
||||||
|
rep.headers.resize(3);
|
||||||
|
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||||
|
rep.headers[0].value = "*";
|
||||||
|
rep.headers[1].name = "Content-Length";
|
||||||
|
|
||||||
|
std::string s;
|
||||||
|
intToString(rep.content.size(), s);
|
||||||
|
|
||||||
|
rep.headers[1].value = s;
|
||||||
|
rep.headers[2].name = "Content-Type";
|
||||||
|
rep.headers[2].value = "text/html";
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Reply::ToString(Reply::status_type status) {
|
||||||
|
switch (status) {
|
||||||
|
case Reply::ok:
|
||||||
|
return okHTML;
|
||||||
|
case Reply::badRequest:
|
||||||
|
return badRequestHTML;
|
||||||
|
default:
|
||||||
|
return internalServerErrorHTML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) {
|
||||||
|
switch (status) {
|
||||||
|
case Reply::ok:
|
||||||
|
return boost::asio::buffer(okString);
|
||||||
|
case Reply::internalServerError:
|
||||||
|
return boost::asio::buffer(internalServerErrorString);
|
||||||
|
default:
|
||||||
|
return boost::asio::buffer(badRequestString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reply::Reply() : status(ok) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 REPLY_H
|
||||||
|
#define REPLY_H
|
||||||
|
|
||||||
|
#include "Header.h"
|
||||||
|
#include "../../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
const char okHTML[] = "";
|
||||||
|
const char badRequestHTML[] = "<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>";
|
||||||
|
const char internalServerErrorHTML[] = "<html><head><title>Internal Server Error</title></head><body><h1>500 Internal Server Error</h1></body></html>";
|
||||||
|
const char seperators[] = { ':', ' ' };
|
||||||
|
const char crlf[] = { '\r', '\n' };
|
||||||
|
const std::string okString = "HTTP/1.0 200 OK\r\n";
|
||||||
|
const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||||
|
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||||
|
|
||||||
|
class Reply {
|
||||||
|
public:
|
||||||
|
enum status_type {
|
||||||
|
ok = 200,
|
||||||
|
badRequest = 400,
|
||||||
|
internalServerError = 500
|
||||||
|
} status;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Header> headers;
|
||||||
|
std::vector<boost::asio::const_buffer> toBuffers();
|
||||||
|
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||||
|
std::vector<std::string> content;
|
||||||
|
static Reply StockReply(status_type status);
|
||||||
|
void setSize(const unsigned size);
|
||||||
|
Reply();
|
||||||
|
private:
|
||||||
|
static std::string ToString(Reply::status_type status);
|
||||||
|
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //REPLY_H
|
||||||
@@ -25,54 +25,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SIMPLESTACK_H_
|
#ifndef REQUEST_H
|
||||||
#define SIMPLESTACK_H_
|
#define REQUEST_H
|
||||||
|
|
||||||
#include <cassert>
|
#include "../../Util/StringUtil.h"
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
template<typename StackItemT, class ContainerT = std::vector<StackItemT> >
|
#include <boost/asio.hpp>
|
||||||
class SimpleStack {
|
|
||||||
|
|
||||||
private:
|
#include <string>
|
||||||
int last;
|
|
||||||
ContainerT arr;
|
|
||||||
|
|
||||||
public:
|
namespace http {
|
||||||
SimpleStack() : last(-1) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleStack(std::size_t size_hint) : last(-1) {
|
struct Request {
|
||||||
hint(size_hint);
|
std::string uri;
|
||||||
}
|
std::string referrer;
|
||||||
|
std::string agent;
|
||||||
inline void hint(std::size_t size_hint) {
|
boost::asio::ip::address endpoint;
|
||||||
arr.reserve(size_hint);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void push(StackItemT t) {
|
|
||||||
++last;
|
|
||||||
arr.push_back(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void pop() {
|
|
||||||
arr.pop_back();
|
|
||||||
--last;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline StackItemT top() {
|
|
||||||
assert (last >= 0);
|
|
||||||
return arr[last];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int size() {
|
|
||||||
return last+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool empty() {
|
|
||||||
return (-1 == last);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace http
|
||||||
|
|
||||||
#endif /* SIMPLESTACK_H_ */
|
#endif //REQUEST_H
|
||||||
+12
-10
@@ -29,8 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define REQUEST_HANDLER_H
|
#define REQUEST_HANDLER_H
|
||||||
|
|
||||||
#include "APIGrammar.h"
|
#include "APIGrammar.h"
|
||||||
#include "BasicDatastructures.h"
|
|
||||||
#include "DataStructures/RouteParameters.h"
|
#include "DataStructures/RouteParameters.h"
|
||||||
|
#include "Http/Request.h"
|
||||||
#include "../Library/OSRM.h"
|
#include "../Library/OSRM.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
@@ -81,20 +81,22 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ( !result || (it != request.end()) ) {
|
if ( !result || (it != request.end()) ) {
|
||||||
rep = http::Reply::stockReply(http::Reply::badRequest);
|
rep = http::Reply::StockReply(http::Reply::badRequest);
|
||||||
const int position = std::distance(request.begin(), it);
|
const int position = std::distance(request.begin(), it);
|
||||||
std::string tmp_position_string;
|
std::string tmp_position_string;
|
||||||
intToString(position, tmp_position_string);
|
intToString(position, tmp_position_string);
|
||||||
rep.content += "Input seems to be malformed close to position ";
|
rep.content.push_back(
|
||||||
rep.content += "<br><pre>";
|
"Input seems to be malformed close to position "
|
||||||
rep.content += request;
|
"<br><pre>"
|
||||||
rep.content += tmp_position_string;
|
);
|
||||||
rep.content += "<br>";
|
rep.content.push_back( request );
|
||||||
|
rep.content.push_back(tmp_position_string);
|
||||||
|
rep.content.push_back("<br>");
|
||||||
const unsigned end = std::distance(request.begin(), it);
|
const unsigned end = std::distance(request.begin(), it);
|
||||||
for(unsigned i = 0; i < end; ++i) {
|
for(unsigned i = 0; i < end; ++i) {
|
||||||
rep.content += " ";
|
rep.content.push_back(" ");
|
||||||
}
|
}
|
||||||
rep.content += "^<br></pre>";
|
rep.content.push_back("^<br></pre>");
|
||||||
} else {
|
} else {
|
||||||
//parsing done, lets call the right plugin to handle the request
|
//parsing done, lets call the right plugin to handle the request
|
||||||
BOOST_ASSERT_MSG(
|
BOOST_ASSERT_MSG(
|
||||||
@@ -105,7 +107,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
rep = http::Reply::stockReply(http::Reply::internalServerError);
|
rep = http::Reply::StockReply(http::Reply::internalServerError);
|
||||||
SimpleLogger().Write(logWARNING) <<
|
SimpleLogger().Write(logWARNING) <<
|
||||||
"[server error] code: " << e.what() << ", uri: " << req.uri;
|
"[server error] code: " << e.what() << ", uri: " << req.uri;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "RequestParser.h"
|
||||||
|
|
||||||
|
namespace http {
|
||||||
|
|
||||||
|
RequestParser::RequestParser() : state_(method_start) { }
|
||||||
|
|
||||||
|
void RequestParser::Reset() { state_ = method_start; }
|
||||||
|
|
||||||
|
boost::tuple<boost::tribool, char*> RequestParser::Parse(
|
||||||
|
Request& req,
|
||||||
|
char* begin,
|
||||||
|
char* end,
|
||||||
|
http::CompressionType * compressionType
|
||||||
|
) {
|
||||||
|
while (begin != end) {
|
||||||
|
boost::tribool result = consume(req, *begin++, compressionType);
|
||||||
|
if (result || !result){
|
||||||
|
return boost::make_tuple(result, begin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boost::tribool result = boost::indeterminate;
|
||||||
|
return boost::make_tuple(result, begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::tribool RequestParser::consume(
|
||||||
|
Request& req, char input,
|
||||||
|
http::CompressionType * compressionType
|
||||||
|
) {
|
||||||
|
switch (state_) {
|
||||||
|
case method_start:
|
||||||
|
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
state_ = method;
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case method:
|
||||||
|
if (input == ' ') {
|
||||||
|
state_ = uri;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case uri_start:
|
||||||
|
if (isCTL(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
state_ = uri;
|
||||||
|
req.uri.push_back(input);
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case uri:
|
||||||
|
if (input == ' ') {
|
||||||
|
state_ = http_version_h;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (isCTL(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
req.uri.push_back(input);
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case http_version_h:
|
||||||
|
if (input == 'H') {
|
||||||
|
state_ = http_version_t_1;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_t_1:
|
||||||
|
if (input == 'T') {
|
||||||
|
state_ = http_version_t_2;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_t_2:
|
||||||
|
if (input == 'T') {
|
||||||
|
state_ = http_version_p;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_p:
|
||||||
|
if (input == 'P') {
|
||||||
|
state_ = http_version_slash;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_slash:
|
||||||
|
if (input == '/') {
|
||||||
|
state_ = http_version_major_start;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_major_start:
|
||||||
|
if (isDigit(input)) {
|
||||||
|
state_ = http_version_major;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_major:
|
||||||
|
if (input == '.') {
|
||||||
|
state_ = http_version_minor_start;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (isDigit(input)) {
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_minor_start:
|
||||||
|
if (isDigit(input)) {
|
||||||
|
state_ = http_version_minor;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case http_version_minor:
|
||||||
|
if (input == '\r') {
|
||||||
|
state_ = expecting_newline_1;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (isDigit(input)) {
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case expecting_newline_1:
|
||||||
|
if (input == '\n') {
|
||||||
|
state_ = header_line_start;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case header_line_start:
|
||||||
|
if(header.name == "Accept-Encoding") {
|
||||||
|
/* giving gzip precedence over deflate */
|
||||||
|
if(header.value.find("deflate") != std::string::npos)
|
||||||
|
*compressionType = deflateRFC1951;
|
||||||
|
if(header.value.find("gzip") != std::string::npos)
|
||||||
|
*compressionType = gzipRFC1952;
|
||||||
|
}
|
||||||
|
|
||||||
|
if("Referer" == header.name)
|
||||||
|
req.referrer = header.value;
|
||||||
|
|
||||||
|
if("User-Agent" == header.name)
|
||||||
|
req.agent = header.value;
|
||||||
|
|
||||||
|
if (input == '\r') {
|
||||||
|
state_ = expecting_newline_3;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
state_ = header_name;
|
||||||
|
header.Clear();
|
||||||
|
header.name.push_back(input);
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case header_lws:
|
||||||
|
if (input == '\r') {
|
||||||
|
state_ = expecting_newline_2;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (input == ' ' || input == '\t') {
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
else if (isCTL(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
state_ = header_value;
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case header_name:
|
||||||
|
if (input == ':') {
|
||||||
|
state_ = space_before_header_value;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
header.name.push_back(input);
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case space_before_header_value:
|
||||||
|
if (input == ' ') {
|
||||||
|
state_ = header_value;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case header_value:
|
||||||
|
if (input == '\r') {
|
||||||
|
state_ = expecting_newline_2;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else if (isCTL(input)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
header.value.push_back(input);
|
||||||
|
return boost::indeterminate;
|
||||||
|
}
|
||||||
|
case expecting_newline_2:
|
||||||
|
if (input == '\n') {
|
||||||
|
state_ = header_line_start;
|
||||||
|
return boost::indeterminate;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case expecting_newline_3:
|
||||||
|
return (input == '\n');
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RequestParser::isChar(int c) {
|
||||||
|
return c >= 0 && c <= 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RequestParser::isCTL(int c) {
|
||||||
|
return (c >= 0 && c <= 31) || (c == 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RequestParser::isTSpecial(int c) {
|
||||||
|
switch (c) {
|
||||||
|
case '(': case ')': case '<': case '>': case '@':
|
||||||
|
case ',': case ';': case ':': case '\\': case '"':
|
||||||
|
case '/': case '[': case ']': case '?': case '=':
|
||||||
|
case '{': case '}': case ' ': case '\t':
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool RequestParser::isDigit(int c) {
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+20
-223
@@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef REQUEST_PARSER_H
|
#ifndef REQUEST_PARSER_H
|
||||||
#define REQUEST_PARSER_H
|
#define REQUEST_PARSER_H
|
||||||
|
|
||||||
#include "BasicDatastructures.h"
|
#include "Http/CompressionType.h"
|
||||||
|
#include "Http/Header.h"
|
||||||
|
#include "Http/Request.h"
|
||||||
|
|
||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
@@ -37,235 +39,30 @@ namespace http {
|
|||||||
|
|
||||||
class RequestParser {
|
class RequestParser {
|
||||||
public:
|
public:
|
||||||
RequestParser() : state_(method_start) { }
|
RequestParser();
|
||||||
void Reset() { state_ = method_start; }
|
void Reset();
|
||||||
|
|
||||||
boost::tuple<boost::tribool, char*> Parse(Request& req, char* begin, char* end, CompressionType * compressionType) {
|
boost::tuple<boost::tribool, char*> Parse(
|
||||||
while (begin != end) {
|
Request& req,
|
||||||
boost::tribool result = consume(req, *begin++, compressionType);
|
char* begin,
|
||||||
if (result || !result){
|
char* end,
|
||||||
return boost::make_tuple(result, begin);
|
CompressionType * compressionType
|
||||||
}
|
);
|
||||||
}
|
|
||||||
boost::tribool result = boost::indeterminate;
|
|
||||||
return boost::make_tuple(result, begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::tribool consume(Request& req, char input, CompressionType * compressionType) {
|
boost::tribool consume(
|
||||||
switch (state_) {
|
Request& req,
|
||||||
case method_start:
|
char input,
|
||||||
if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
CompressionType * compressionType
|
||||||
return false;
|
);
|
||||||
} else {
|
|
||||||
state_ = method;
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case method:
|
|
||||||
if (input == ' ') {
|
|
||||||
state_ = uri;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case uri_start:
|
|
||||||
if (isCTL(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
state_ = uri;
|
|
||||||
req.uri.push_back(input);
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case uri:
|
|
||||||
if (input == ' ') {
|
|
||||||
state_ = http_version_h;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (isCTL(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
req.uri.push_back(input);
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case http_version_h:
|
|
||||||
if (input == 'H') {
|
|
||||||
state_ = http_version_t_1;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_t_1:
|
|
||||||
if (input == 'T') {
|
|
||||||
state_ = http_version_t_2;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_t_2:
|
|
||||||
if (input == 'T') {
|
|
||||||
state_ = http_version_p;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_p:
|
|
||||||
if (input == 'P') {
|
|
||||||
state_ = http_version_slash;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_slash:
|
|
||||||
if (input == '/') {
|
|
||||||
state_ = http_version_major_start;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_major_start:
|
|
||||||
if (isDigit(input)) {
|
|
||||||
state_ = http_version_major;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_major:
|
|
||||||
if (input == '.') {
|
|
||||||
state_ = http_version_minor_start;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (isDigit(input)) {
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_minor_start:
|
|
||||||
if (isDigit(input)) {
|
|
||||||
state_ = http_version_minor;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case http_version_minor:
|
|
||||||
if (input == '\r') {
|
|
||||||
state_ = expecting_newline_1;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (isDigit(input)) {
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case expecting_newline_1:
|
|
||||||
if (input == '\n') {
|
|
||||||
state_ = header_line_start;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case header_line_start:
|
|
||||||
if(header.name == "Accept-Encoding") {
|
|
||||||
/* giving gzip precedence over deflate */
|
|
||||||
if(header.value.find("deflate") != std::string::npos)
|
|
||||||
*compressionType = deflateRFC1951;
|
|
||||||
if(header.value.find("gzip") != std::string::npos)
|
|
||||||
*compressionType = gzipRFC1952;
|
|
||||||
}
|
|
||||||
|
|
||||||
if("Referer" == header.name)
|
inline bool isChar(int c);
|
||||||
req.referrer = header.value;
|
|
||||||
|
|
||||||
if("User-Agent" == header.name)
|
inline bool isCTL(int c);
|
||||||
req.agent = header.value;
|
|
||||||
|
|
||||||
if (input == '\r') {
|
inline bool isTSpecial(int c);
|
||||||
state_ = expecting_newline_3;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
state_ = header_name;
|
|
||||||
header.Clear();
|
|
||||||
header.name.push_back(input);
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case header_lws:
|
|
||||||
if (input == '\r') {
|
|
||||||
state_ = expecting_newline_2;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (input == ' ' || input == '\t') {
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
else if (isCTL(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
state_ = header_value;
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case header_name:
|
|
||||||
if (input == ':') {
|
|
||||||
state_ = space_before_header_value;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (!isChar(input) || isCTL(input) || isTSpecial(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
header.name.push_back(input);
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case space_before_header_value:
|
|
||||||
if (input == ' ') {
|
|
||||||
state_ = header_value;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case header_value:
|
|
||||||
if (input == '\r') {
|
|
||||||
state_ = expecting_newline_2;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else if (isCTL(input)) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
header.value.push_back(input);
|
|
||||||
return boost::indeterminate;
|
|
||||||
}
|
|
||||||
case expecting_newline_2:
|
|
||||||
if (input == '\n') {
|
|
||||||
state_ = header_line_start;
|
|
||||||
return boost::indeterminate;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case expecting_newline_3:
|
|
||||||
return (input == '\n');
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isChar(int c) {
|
inline bool isDigit(int c);
|
||||||
return c >= 0 && c <= 127;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isCTL(int c) {
|
|
||||||
return (c >= 0 && c <= 31) || (c == 127);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isTSpecial(int c) {
|
|
||||||
switch (c) {
|
|
||||||
case '(': case ')': case '<': case '>': case '@':
|
|
||||||
case ',': case ';': case ':': case '\\': case '"':
|
|
||||||
case '/': case '[': case ']': case '?': case '=':
|
|
||||||
case '{': case '}': case ' ': case '\t':
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isDigit(int c) {
|
|
||||||
return c >= '0' && c <= '9';
|
|
||||||
}
|
|
||||||
|
|
||||||
enum state {
|
enum state {
|
||||||
method_start,
|
method_start,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../Util/GitDescription.h"
|
||||||
#include "../Util/OSRMException.h"
|
#include "../Util/OSRMException.h"
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/TimingUtil.h"
|
#include "../Util/TimingUtil.h"
|
||||||
@@ -74,8 +75,9 @@ void RunStatistics(std::vector<double> & timings_vector, Statistics & stats) {
|
|||||||
int main (int argc, char * argv[]) {
|
int main (int argc, char * argv[]) {
|
||||||
LogPolicy::GetInstance().Unmute();
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
|
||||||
SimpleLogger().Write(logDEBUG) << "starting up engines, compiled at " <<
|
SimpleLogger().Write() <<
|
||||||
__DATE__ << ", " __TIME__;
|
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||||
|
"compiled at " << __DATE__ << ", " __TIME__;
|
||||||
|
|
||||||
if( 1 == argc ) {
|
if( 1 == argc ) {
|
||||||
SimpleLogger().Write(logWARNING) <<
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ int main (int argc, const char * argv[]) {
|
|||||||
try {
|
try {
|
||||||
std::string ip_address;
|
std::string ip_address;
|
||||||
int ip_port, requested_num_threads;
|
int ip_port, requested_num_threads;
|
||||||
|
bool use_shared_memory = false;
|
||||||
ServerPaths server_paths;
|
ServerPaths server_paths;
|
||||||
if( !GenerateServerProgramOptions(
|
if( !GenerateServerProgramOptions(
|
||||||
argc,
|
argc,
|
||||||
@@ -63,7 +63,8 @@ int main (int argc, const char * argv[]) {
|
|||||||
server_paths,
|
server_paths,
|
||||||
ip_address,
|
ip_address,
|
||||||
ip_port,
|
ip_port,
|
||||||
requested_num_threads
|
requested_num_threads,
|
||||||
|
use_shared_memory
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -73,7 +74,7 @@ int main (int argc, const char * argv[]) {
|
|||||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||||
"compiled at " << __DATE__ << ", " __TIME__;
|
"compiled at " << __DATE__ << ", " __TIME__;
|
||||||
|
|
||||||
OSRM routing_machine(server_paths);
|
OSRM routing_machine( server_paths, use_shared_memory );
|
||||||
|
|
||||||
RouteParameters route_parameters;
|
RouteParameters route_parameters;
|
||||||
route_parameters.zoomLevel = 18; //no generalization
|
route_parameters.zoomLevel = 18; //no generalization
|
||||||
@@ -97,12 +98,14 @@ int main (int argc, const char * argv[]) {
|
|||||||
|
|
||||||
routing_machine.RunQuery(route_parameters, osrm_reply);
|
routing_machine.RunQuery(route_parameters, osrm_reply);
|
||||||
|
|
||||||
std::cout << osrm_reply.content << std::endl;
|
|
||||||
|
|
||||||
//attention: super-inefficient hack below:
|
//attention: super-inefficient hack below:
|
||||||
|
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << osrm_reply.content;
|
BOOST_FOREACH(const std::string & line, osrm_reply.content) {
|
||||||
|
std::cout << line;
|
||||||
|
ss << line;
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
boost::property_tree::ptree pt;
|
boost::property_tree::ptree pt;
|
||||||
boost::property_tree::read_json(ss, pt);
|
boost::property_tree::read_json(ss, pt);
|
||||||
|
|||||||
@@ -25,30 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CRC32_H_
|
#include "../Util/GitDescription.h"
|
||||||
#define CRC32_H_
|
|
||||||
|
|
||||||
#include "../Util/SimpleLogger.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Server/DataStructures/SharedBarriers.h"
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
class CRC32 {
|
int main() {
|
||||||
private:
|
LogPolicy::GetInstance().Unmute();
|
||||||
unsigned crc;
|
SimpleLogger().Write() <<
|
||||||
|
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
"compiled at " << __DATE__ << ", " __TIME__;
|
||||||
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
SimpleLogger().Write() << "Releasing all locks";
|
||||||
|
SharedBarriers barrier;
|
||||||
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned crc);
|
barrier.pending_update_mutex.unlock();
|
||||||
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc);
|
barrier.query_mutex.unlock();
|
||||||
unsigned cpuid(unsigned functionInput);
|
barrier.update_mutex.unlock();
|
||||||
CRC32CFunctionPtr detectBestCRC32C();
|
return 0;
|
||||||
CRC32CFunctionPtr crcFunction;
|
}
|
||||||
public:
|
|
||||||
CRC32();
|
|
||||||
unsigned operator()(char *str, unsigned len);
|
|
||||||
virtual ~CRC32() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* CRC32_H_ */
|
|
||||||
@@ -25,40 +25,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef QUERYOBJECTSSTORAGE_H_
|
#ifndef BOOST_FILE_SYSTEM_FIX_H
|
||||||
#define QUERYOBJECTSSTORAGE_H_
|
#define BOOST_FILE_SYSTEM_FIX_H
|
||||||
|
|
||||||
#include "../../Util/GraphLoader.h"
|
|
||||||
#include "../../Util/OSRMException.h"
|
|
||||||
#include "../../Util/ProgramOptions.h"
|
|
||||||
#include "../../Util/SimpleLogger.h"
|
|
||||||
#include "../../DataStructures/NodeInformationHelpDesk.h"
|
|
||||||
#include "../../DataStructures/QueryEdge.h"
|
|
||||||
#include "../../DataStructures/StaticGraph.h"
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
//This is one big workaround for latest boost renaming woes.
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
#if BOOST_FILESYSTEM_VERSION < 3
|
||||||
|
#warning Boost Installation with Filesystem3 missing, activating workaround
|
||||||
|
#include <cstdio>
|
||||||
|
namespace boost {
|
||||||
|
namespace filesystem {
|
||||||
|
inline path temp_directory_path() {
|
||||||
|
char * buffer;
|
||||||
|
buffer = tmpnam (NULL);
|
||||||
|
|
||||||
struct QueryObjectsStorage {
|
return path(buffer);
|
||||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
}
|
||||||
typedef QueryGraph::InputEdge InputEdge;
|
|
||||||
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
inline path unique_path(const path&) {
|
||||||
std::vector<char> m_names_char_list;
|
return temp_directory_path();
|
||||||
std::vector<unsigned> m_name_begin_indices;
|
}
|
||||||
QueryGraph * graph;
|
|
||||||
std::string timestamp;
|
|
||||||
unsigned check_sum;
|
|
||||||
|
|
||||||
void GetName( const unsigned name_id, std::string & result ) const;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QueryObjectsStorage( const ServerPaths & paths );
|
#endif
|
||||||
~QueryObjectsStorage();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* QUERYOBJECTSSTORAGE_H_ */
|
#ifndef BOOST_FILESYSTEM_VERSION
|
||||||
|
#define BOOST_FILESYSTEM_VERSION 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* BOOST_FILE_SYSTEM_FIX_H */
|
||||||
+82
-80
@@ -42,7 +42,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -54,7 +53,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
|
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
|
||||||
|
|
||||||
template<class EdgeT>
|
template<class EdgeT>
|
||||||
struct _ExcessRemover {
|
struct NodesWithoutSourceRemover {
|
||||||
inline bool operator()( const EdgeT & edge ) const {
|
inline bool operator()( const EdgeT & edge ) const {
|
||||||
return edge.source() == UINT_MAX;
|
return edge.source() == UINT_MAX;
|
||||||
}
|
}
|
||||||
@@ -62,16 +61,16 @@ struct _ExcessRemover {
|
|||||||
|
|
||||||
template<typename EdgeT>
|
template<typename EdgeT>
|
||||||
NodeID readBinaryOSRMGraphFromStream(
|
NodeID readBinaryOSRMGraphFromStream(
|
||||||
std::istream &in,
|
std::istream & input_stream,
|
||||||
std::vector<EdgeT>& edgeList,
|
std::vector<EdgeT> & edge_list,
|
||||||
std::vector<NodeID> &bollardNodes,
|
std::vector<NodeID> & barrier_node_list,
|
||||||
std::vector<NodeID> &trafficLightNodes,
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
std::vector<NodeInfo> * int2ExtNodeMap,
|
std::vector<NodeInfo> * int_to_ext_node_id_map,
|
||||||
std::vector<TurnRestriction> & inputRestrictions
|
std::vector<TurnRestriction> & restriction_list
|
||||||
) {
|
) {
|
||||||
const UUID uuid_orig;
|
const UUID uuid_orig;
|
||||||
UUID uuid_loaded;
|
UUID uuid_loaded;
|
||||||
in.read((char *) &uuid_loaded, sizeof(UUID));
|
input_stream.read((char *) &uuid_loaded, sizeof(UUID));
|
||||||
|
|
||||||
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
||||||
SimpleLogger().Write(logWARNING) <<
|
SimpleLogger().Write(logWARNING) <<
|
||||||
@@ -83,29 +82,31 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
EdgeID m;
|
EdgeID m;
|
||||||
short dir;// direction (0 = open, 1 = forward, 2+ = open)
|
short dir;// direction (0 = open, 1 = forward, 2+ = open)
|
||||||
ExternalNodeMap ext_to_int_id_map;
|
ExternalNodeMap ext_to_int_id_map;
|
||||||
in.read((char*)&n, sizeof(NodeID));
|
input_stream.read((char*)&n, sizeof(NodeID));
|
||||||
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
|
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
|
||||||
_Node node;
|
ExternalMemoryNode node;
|
||||||
for (NodeID i=0; i<n; ++i) {
|
for( NodeID i=0; i<n; ++i ) {
|
||||||
in.read((char*)&node, sizeof(_Node));
|
input_stream.read((char*)&node, sizeof(ExternalMemoryNode));
|
||||||
int2ExtNodeMap->push_back(NodeInfo(node.lat, node.lon, node.id));
|
int_to_ext_node_id_map->push_back(
|
||||||
|
NodeInfo(node.lat, node.lon, node.id)
|
||||||
|
);
|
||||||
ext_to_int_id_map.emplace(node.id, i);
|
ext_to_int_id_map.emplace(node.id, i);
|
||||||
if(node.bollard) {
|
if(node.bollard) {
|
||||||
bollardNodes.push_back(i);
|
barrier_node_list.push_back(i);
|
||||||
}
|
}
|
||||||
if(node.trafficLight) {
|
if(node.trafficLight) {
|
||||||
trafficLightNodes.push_back(i);
|
traffic_light_node_list.push_back(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//tighten vector sizes
|
//tighten vector sizes
|
||||||
std::vector<NodeID>(bollardNodes).swap(bollardNodes);
|
std::vector<NodeID>(barrier_node_list).swap(barrier_node_list);
|
||||||
std::vector<NodeID>(trafficLightNodes).swap(trafficLightNodes);
|
std::vector<NodeID>(traffic_light_node_list).swap(traffic_light_node_list);
|
||||||
|
|
||||||
in.read((char*)&m, sizeof(unsigned));
|
input_stream.read((char*)&m, sizeof(unsigned));
|
||||||
SimpleLogger().Write() << " and " << m << " edges ";
|
SimpleLogger().Write() << " and " << m << " edges ";
|
||||||
// for(unsigned i = 0; i < inputRestrictions.size(); ++i) {
|
// for(unsigned i = 0; i < restriction_list.size(); ++i) {
|
||||||
BOOST_FOREACH(TurnRestriction & current_restriction, inputRestrictions) {
|
BOOST_FOREACH(TurnRestriction & current_restriction, restriction_list) {
|
||||||
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(current_restriction.fromNode);
|
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(current_restriction.fromNode);
|
||||||
if( intNodeID == ext_to_int_id_map.end()) {
|
if( intNodeID == ext_to_int_id_map.end()) {
|
||||||
SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
|
SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
|
||||||
@@ -129,7 +130,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
current_restriction.toNode = intNodeID->second;
|
current_restriction.toNode = intNodeID->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeList.reserve(m);
|
edge_list.reserve(m);
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
short type;
|
short type;
|
||||||
NodeID nameID;
|
NodeID nameID;
|
||||||
@@ -137,17 +138,17 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
|
bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow;
|
||||||
|
|
||||||
for (EdgeID i=0; i<m; ++i) {
|
for (EdgeID i=0; i<m; ++i) {
|
||||||
in.read((char*)&source, sizeof(unsigned));
|
input_stream.read((char*)&source, sizeof(unsigned));
|
||||||
in.read((char*)&target, sizeof(unsigned));
|
input_stream.read((char*)&target, sizeof(unsigned));
|
||||||
in.read((char*)&length, sizeof(int));
|
input_stream.read((char*)&length, sizeof(int));
|
||||||
in.read((char*)&dir, sizeof(short));
|
input_stream.read((char*)&dir, sizeof(short));
|
||||||
in.read((char*)&weight, sizeof(int));
|
input_stream.read((char*)&weight, sizeof(int));
|
||||||
in.read((char*)&type, sizeof(short));
|
input_stream.read((char*)&type, sizeof(short));
|
||||||
in.read((char*)&nameID, sizeof(unsigned));
|
input_stream.read((char*)&nameID, sizeof(unsigned));
|
||||||
in.read((char*)&isRoundabout, sizeof(bool));
|
input_stream.read((char*)&isRoundabout, sizeof(bool));
|
||||||
in.read((char*)&ignoreInGrid, sizeof(bool));
|
input_stream.read((char*)&ignoreInGrid, sizeof(bool));
|
||||||
in.read((char*)&isAccessRestricted, sizeof(bool));
|
input_stream.read((char*)&isAccessRestricted, sizeof(bool));
|
||||||
in.read((char*)&isContraFlow, sizeof(bool));
|
input_stream.read((char*)&isContraFlow, sizeof(bool));
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
|
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
|
||||||
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||||
@@ -158,7 +159,7 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
if (1 == dir) { backward = false; }
|
if (1 == dir) { backward = false; }
|
||||||
if (2 == dir) { forward = false; }
|
if (2 == dir) { forward = false; }
|
||||||
|
|
||||||
assert(type >= 0);
|
BOOST_ASSERT(type >= 0);
|
||||||
|
|
||||||
// translate the external NodeIDs to internal IDs
|
// translate the external NodeIDs to internal IDs
|
||||||
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(source);
|
ExternalNodeMap::iterator intNodeID = ext_to_int_id_map.find(source);
|
||||||
@@ -189,47 +190,52 @@ NodeID readBinaryOSRMGraphFromStream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
|
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
|
||||||
edgeList.push_back(inputEdge);
|
edge_list.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
std::sort(edgeList.begin(), edgeList.end());
|
std::sort(edge_list.begin(), edge_list.end());
|
||||||
for(unsigned i = 1; i < edgeList.size(); ++i) {
|
for(unsigned i = 1; i < edge_list.size(); ++i) {
|
||||||
if( (edgeList[i-1].target() == edgeList[i].target()) && (edgeList[i-1].source() == edgeList[i].source()) ) {
|
if( (edge_list[i-1].target() == edge_list[i].target()) && (edge_list[i-1].source() == edge_list[i].source()) ) {
|
||||||
bool edgeFlagsAreEquivalent = (edgeList[i-1].isForward() == edgeList[i].isForward()) && (edgeList[i-1].isBackward() == edgeList[i].isBackward());
|
bool edgeFlagsAreEquivalent = (edge_list[i-1].isForward() == edge_list[i].isForward()) && (edge_list[i-1].isBackward() == edge_list[i].isBackward());
|
||||||
bool edgeFlagsAreSuperSet1 = (edgeList[i-1].isForward() && edgeList[i-1].isBackward()) && (edgeList[i].isBackward() != edgeList[i].isBackward() );
|
bool edgeFlagsAreSuperSet1 = (edge_list[i-1].isForward() && edge_list[i-1].isBackward()) && (edge_list[i].isBackward() != edge_list[i].isBackward() );
|
||||||
bool edgeFlagsAreSuperSet2 = (edgeList[i].isForward() && edgeList[i].isBackward()) && (edgeList[i-1].isBackward() != edgeList[i-1].isBackward() );
|
bool edgeFlagsAreSuperSet2 = (edge_list[i].isForward() && edge_list[i].isBackward()) && (edge_list[i-1].isBackward() != edge_list[i-1].isBackward() );
|
||||||
|
|
||||||
if( edgeFlagsAreEquivalent ) {
|
if( edgeFlagsAreEquivalent ) {
|
||||||
edgeList[i]._weight = std::min(edgeList[i-1].weight(), edgeList[i].weight());
|
edge_list[i]._weight = std::min(edge_list[i-1].weight(), edge_list[i].weight());
|
||||||
edgeList[i-1]._source = UINT_MAX;
|
edge_list[i-1]._source = UINT_MAX;
|
||||||
} else if (edgeFlagsAreSuperSet1) {
|
} else if (edgeFlagsAreSuperSet1) {
|
||||||
if(edgeList[i-1].weight() <= edgeList[i].weight()) {
|
if(edge_list[i-1].weight() <= edge_list[i].weight()) {
|
||||||
//edge i-1 is smaller and goes in both directions. Throw away the other edge
|
//edge i-1 is smaller and goes in both directions. Throw away the other edge
|
||||||
edgeList[i]._source = UINT_MAX;
|
edge_list[i]._source = UINT_MAX;
|
||||||
} else {
|
} else {
|
||||||
//edge i-1 is open in both directions, but edge i is smaller in one direction. Close edge i-1 in this direction
|
//edge i-1 is open in both directions, but edge i is smaller in one direction. Close edge i-1 in this direction
|
||||||
edgeList[i-1].forward = !edgeList[i].isForward();
|
edge_list[i-1].forward = !edge_list[i].isForward();
|
||||||
edgeList[i-1].backward = !edgeList[i].isBackward();
|
edge_list[i-1].backward = !edge_list[i].isBackward();
|
||||||
}
|
}
|
||||||
} else if (edgeFlagsAreSuperSet2) {
|
} else if (edgeFlagsAreSuperSet2) {
|
||||||
if(edgeList[i-1].weight() <= edgeList[i].weight()) {
|
if(edge_list[i-1].weight() <= edge_list[i].weight()) {
|
||||||
//edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction
|
//edge i-1 is smaller for one direction. edge i is open in both. close edge i in the other direction
|
||||||
edgeList[i].forward = !edgeList[i-1].isForward();
|
edge_list[i].forward = !edge_list[i-1].isForward();
|
||||||
edgeList[i].backward = !edgeList[i-1].isBackward();
|
edge_list[i].backward = !edge_list[i-1].isBackward();
|
||||||
} else {
|
} else {
|
||||||
//edge i is smaller and goes in both direction. Throw away edge i-1
|
//edge i is smaller and goes in both direction. Throw away edge i-1
|
||||||
edgeList[i-1]._source = UINT_MAX;
|
edge_list[i-1]._source = UINT_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
|
typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edge_list.begin(), edge_list.end(), NodesWithoutSourceRemover<EdgeT>());
|
||||||
ext_to_int_id_map.clear();
|
ext_to_int_id_map.clear();
|
||||||
std::vector<EdgeT>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edge_list.begin(), newEnd).swap(edge_list); //remove excess candidates.
|
||||||
SimpleLogger().Write() << "Graph loaded ok and has " << edgeList.size() << " edges";
|
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename EdgeT>
|
template<typename EdgeT>
|
||||||
NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeInfo> * int2ExtNodeMap) {
|
NodeID readDTMPGraphFromStream(
|
||||||
|
std::istream &in,
|
||||||
|
std::vector<EdgeT>& edge_list,
|
||||||
|
std::vector<NodeInfo> * int_to_ext_node_id_map
|
||||||
|
) {
|
||||||
NodeID n, source, target, id;
|
NodeID n, source, target, id;
|
||||||
EdgeID m;
|
EdgeID m;
|
||||||
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
|
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
|
||||||
@@ -238,13 +244,13 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
SimpleLogger().Write(logDEBUG) << "Importing n = " << n << " nodes ";
|
SimpleLogger().Write(logDEBUG) << "Importing n = " << n << " nodes ";
|
||||||
for (NodeID i=0; i<n; ++i) {
|
for (NodeID i=0; i<n; ++i) {
|
||||||
in >> id >> ycoord >> xcoord;
|
in >> id >> ycoord >> xcoord;
|
||||||
int2ExtNodeMap->push_back(NodeInfo(xcoord, ycoord, id));
|
int_to_ext_node_id_map->push_back(NodeInfo(xcoord, ycoord, id));
|
||||||
ext_to_int_id_map.insert(std::make_pair(id, i));
|
ext_to_int_id_map.insert(std::make_pair(id, i));
|
||||||
}
|
}
|
||||||
in >> m;
|
in >> m;
|
||||||
SimpleLogger().Write(logDEBUG) << " and " << m << " edges";
|
SimpleLogger().Write(logDEBUG) << " and " << m << " edges";
|
||||||
|
|
||||||
edgeList.reserve(m);
|
edge_list.reserve(m);
|
||||||
for (EdgeID i=0; i<m; ++i) {
|
for (EdgeID i=0; i<m; ++i) {
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
unsigned speedType(0);
|
unsigned speedType(0);
|
||||||
@@ -308,12 +314,12 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
if(speedType == 13) {
|
if(speedType == 13) {
|
||||||
weight = length;
|
weight = length;
|
||||||
}
|
}
|
||||||
assert(length > 0);
|
BOOST_ASSERT(length > 0);
|
||||||
assert(weight > 0);
|
BOOST_ASSERT(weight > 0);
|
||||||
if(dir <0 || dir > 2) {
|
if(dir <0 || dir > 2) {
|
||||||
SimpleLogger().Write(logWARNING) << "direction bogus: " << dir;
|
SimpleLogger().Write(logWARNING) << "direction bogus: " << dir;
|
||||||
}
|
}
|
||||||
assert(0<=dir && dir<=2);
|
BOOST_ASSERT(0<=dir && dir<=2);
|
||||||
|
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
bool backward = true;
|
bool backward = true;
|
||||||
@@ -345,16 +351,16 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
|
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
|
||||||
edgeList.push_back(inputEdge);
|
edge_list.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
ext_to_int_id_map.clear();
|
ext_to_int_id_map.clear();
|
||||||
std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edge_list.begin(), edge_list.end()).swap(edge_list); //remove excess candidates.
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename EdgeT>
|
template<typename EdgeT>
|
||||||
NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> & int2ExtNodeMap) {
|
NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edge_list, std::vector<NodeID> & int_to_ext_node_id_map) {
|
||||||
ExternalNodeMap nodeMap;
|
ExternalNodeMap nodeMap;
|
||||||
NodeID n, source, target;
|
NodeID n, source, target;
|
||||||
unsigned numberOfNodes = 0;
|
unsigned numberOfNodes = 0;
|
||||||
@@ -368,16 +374,16 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
SimpleLogger().Write(logDEBUG) <<
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
"expecting " << n << " nodes and " << m << " edges ...";
|
"expecting " << n << " nodes and " << m << " edges ...";
|
||||||
|
|
||||||
edgeList.reserve(m);
|
edge_list.reserve(m);
|
||||||
for (EdgeID i=0; i<m; i++) {
|
for (EdgeID i=0; i<m; i++) {
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
in >> source >> target >> weight >> dir;
|
in >> source >> target >> weight >> dir;
|
||||||
|
|
||||||
assert(weight > 0);
|
BOOST_ASSERT(weight > 0);
|
||||||
if(dir <0 || dir > 3) {
|
if(dir <0 || dir > 3) {
|
||||||
throw OSRMException( "[error] direction bogus");
|
throw OSRMException( "[error] direction bogus");
|
||||||
}
|
}
|
||||||
assert(0<=dir && dir<=3);
|
BOOST_ASSERT(0<=dir && dir<=3);
|
||||||
|
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
bool backward = true;
|
bool backward = true;
|
||||||
@@ -391,18 +397,18 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
|
|
||||||
if( nodeMap.find(source) == nodeMap.end()) {
|
if( nodeMap.find(source) == nodeMap.end()) {
|
||||||
nodeMap.insert(std::make_pair(source, numberOfNodes ));
|
nodeMap.insert(std::make_pair(source, numberOfNodes ));
|
||||||
int2ExtNodeMap.push_back(source);
|
int_to_ext_node_id_map.push_back(source);
|
||||||
numberOfNodes++;
|
numberOfNodes++;
|
||||||
}
|
}
|
||||||
if( nodeMap.find(target) == nodeMap.end()) {
|
if( nodeMap.find(target) == nodeMap.end()) {
|
||||||
nodeMap.insert(std::make_pair(target, numberOfNodes));
|
nodeMap.insert(std::make_pair(target, numberOfNodes));
|
||||||
int2ExtNodeMap.push_back(target);
|
int_to_ext_node_id_map.push_back(target);
|
||||||
numberOfNodes++;
|
numberOfNodes++;
|
||||||
}
|
}
|
||||||
EdgeT inputEdge(source, target, 0, weight, forward, backward, 1 );
|
EdgeT inputEdge(source, target, 0, weight, forward, backward, 1 );
|
||||||
edgeList.push_back(inputEdge);
|
edge_list.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edge_list.begin(), edge_list.end()).swap(edge_list); //remove excess candidates.
|
||||||
|
|
||||||
nodeMap.clear();
|
nodeMap.clear();
|
||||||
return numberOfNodes;
|
return numberOfNodes;
|
||||||
@@ -410,12 +416,11 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
|
|
||||||
template<typename NodeT, typename EdgeT>
|
template<typename NodeT, typename EdgeT>
|
||||||
unsigned readHSGRFromStream(
|
unsigned readHSGRFromStream(
|
||||||
const std::string & hsgr_filename,
|
const boost::filesystem::path & hsgr_file,
|
||||||
std::vector<NodeT> & node_list,
|
std::vector<NodeT> & node_list,
|
||||||
std::vector<EdgeT> & edge_list,
|
std::vector<EdgeT> & edge_list,
|
||||||
unsigned * check_sum
|
unsigned * check_sum
|
||||||
) {
|
) {
|
||||||
boost::filesystem::path hsgr_file(hsgr_filename);
|
|
||||||
if ( !boost::filesystem::exists( hsgr_file ) ) {
|
if ( !boost::filesystem::exists( hsgr_file ) ) {
|
||||||
throw OSRMException("hsgr file does not exist");
|
throw OSRMException("hsgr file does not exist");
|
||||||
}
|
}
|
||||||
@@ -434,20 +439,17 @@ unsigned readHSGRFromStream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned number_of_nodes = 0;
|
unsigned number_of_nodes = 0;
|
||||||
hsgr_input_stream.read((char*) check_sum, sizeof(unsigned));
|
unsigned number_of_edges = 0;
|
||||||
hsgr_input_stream.read((char*) & number_of_nodes, sizeof(unsigned));
|
hsgr_input_stream.read( (char*) check_sum, sizeof(unsigned) );
|
||||||
|
hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) );
|
||||||
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
|
BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero");
|
||||||
|
hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) );
|
||||||
|
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
|
||||||
node_list.resize(number_of_nodes + 1);
|
node_list.resize(number_of_nodes + 1);
|
||||||
hsgr_input_stream.read(
|
hsgr_input_stream.read(
|
||||||
(char*) &(node_list[0]),
|
(char*) &(node_list[0]),
|
||||||
number_of_nodes*sizeof(NodeT)
|
number_of_nodes*sizeof(NodeT)
|
||||||
);
|
);
|
||||||
unsigned number_of_edges = 0;
|
|
||||||
hsgr_input_stream.read(
|
|
||||||
(char*) &number_of_edges,
|
|
||||||
sizeof(unsigned)
|
|
||||||
);
|
|
||||||
BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero");
|
|
||||||
|
|
||||||
edge_list.resize(number_of_edges);
|
edge_list.resize(number_of_edges);
|
||||||
hsgr_input_stream.read(
|
hsgr_input_stream.read(
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ public:
|
|||||||
return parameters.Find(key);
|
return parameters.Find(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetParameter(const std::string & key) const {
|
||||||
|
return parameters.Find(key);
|
||||||
|
}
|
||||||
|
|
||||||
bool Holds(const std::string & key) const {
|
bool Holds(const std::string & key) const {
|
||||||
return parameters.Holds(key);
|
return parameters.Holds(key);
|
||||||
}
|
}
|
||||||
|
|||||||
+74
-57
@@ -52,7 +52,7 @@ namespace boost {
|
|||||||
// Validator for boost::filesystem::path, that verifies that the file
|
// Validator for boost::filesystem::path, that verifies that the file
|
||||||
// exists. The validate() function must be defined in the same namespace
|
// exists. The validate() function must be defined in the same namespace
|
||||||
// as the target type, (boost::filesystem::path in this case), otherwise
|
// as the target type, (boost::filesystem::path in this case), otherwise
|
||||||
// it is not be called
|
// it is not called
|
||||||
inline void validate(
|
inline void validate(
|
||||||
boost::any & v,
|
boost::any & v,
|
||||||
const std::vector<std::string> & values,
|
const std::vector<std::string> & values,
|
||||||
@@ -65,20 +65,18 @@ namespace boost {
|
|||||||
if(boost::filesystem::is_regular_file(input_string)) {
|
if(boost::filesystem::is_regular_file(input_string)) {
|
||||||
v = boost::any(boost::filesystem::path(input_string));
|
v = boost::any(boost::filesystem::path(input_string));
|
||||||
} else {
|
} else {
|
||||||
throw OSRMException(input_string);
|
throw OSRMException(input_string + " not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// support old capitalized option names by downcasing them with a regex replace
|
// support old capitalized option names by down-casing them with a regex replace
|
||||||
// read from file and store in a stringstream that can be passed to
|
|
||||||
// boost::program_options
|
|
||||||
inline void PrepareConfigFile(
|
inline void PrepareConfigFile(
|
||||||
const boost::filesystem::path& path,
|
const boost::filesystem::path& path,
|
||||||
std::string& output
|
std::string& output
|
||||||
) {
|
) {
|
||||||
std::ifstream config_stream(path.string().c_str());
|
std::ifstream config_stream( path.string().c_str() );
|
||||||
std::string input_str(
|
std::string input_str(
|
||||||
(std::istreambuf_iterator<char>(config_stream)),
|
(std::istreambuf_iterator<char>(config_stream)),
|
||||||
std::istreambuf_iterator<char>()
|
std::istreambuf_iterator<char>()
|
||||||
@@ -96,7 +94,8 @@ inline bool GenerateServerProgramOptions(
|
|||||||
ServerPaths & paths,
|
ServerPaths & paths,
|
||||||
std::string & ip_address,
|
std::string & ip_address,
|
||||||
int & ip_port,
|
int & ip_port,
|
||||||
int & requested_num_threads
|
int & requested_num_threads,
|
||||||
|
bool & use_shared_memory
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// declare a group of options that will be allowed only on command line
|
// declare a group of options that will be allowed only on command line
|
||||||
@@ -160,6 +159,11 @@ inline bool GenerateServerProgramOptions(
|
|||||||
"threads,t",
|
"threads,t",
|
||||||
boost::program_options::value<int>(&requested_num_threads)->default_value(8),
|
boost::program_options::value<int>(&requested_num_threads)->default_value(8),
|
||||||
"Number of threads to use"
|
"Number of threads to use"
|
||||||
|
)
|
||||||
|
(
|
||||||
|
"sharedmemory,s",
|
||||||
|
boost::program_options::value<bool>(&use_shared_memory)->default_value(false),
|
||||||
|
"Load data from shared memory"
|
||||||
);
|
);
|
||||||
|
|
||||||
// hidden options, will be allowed both on command line and in config
|
// hidden options, will be allowed both on command line and in config
|
||||||
@@ -208,9 +212,12 @@ inline bool GenerateServerProgramOptions(
|
|||||||
boost::program_options::notify(option_variables);
|
boost::program_options::notify(option_variables);
|
||||||
|
|
||||||
// parse config file
|
// parse config file
|
||||||
ServerPaths::const_iterator path_iterator = paths.find("config");
|
ServerPaths::iterator path_iterator = paths.find("config");
|
||||||
if( path_iterator != paths.end() &&
|
if(
|
||||||
boost::filesystem::is_regular_file(path_iterator->second)) {
|
path_iterator != paths.end() &&
|
||||||
|
boost::filesystem::is_regular_file(path_iterator->second) &&
|
||||||
|
!option_variables.count("base")
|
||||||
|
) {
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() <<
|
||||||
"Reading options from: " << path_iterator->second.string();
|
"Reading options from: " << path_iterator->second.string();
|
||||||
std::string config_str;
|
std::string config_str;
|
||||||
@@ -223,56 +230,66 @@ inline bool GenerateServerProgramOptions(
|
|||||||
boost::program_options::notify(option_variables);
|
boost::program_options::notify(option_variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!option_variables.count("hsgrdata")) {
|
if( !use_shared_memory && option_variables.count("base") ) {
|
||||||
if(!option_variables.count("base")) {
|
std::string base_string = paths["base"].string();
|
||||||
throw OSRMException("hsgrdata (or base) must be specified");
|
path_iterator = paths.find("hsgrdata");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".hsgr";
|
||||||
|
}
|
||||||
|
|
||||||
|
path_iterator = paths.find("nodesdata");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".nodes";
|
||||||
|
}
|
||||||
|
|
||||||
|
path_iterator = paths.find("edgesdata");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".edges";
|
||||||
|
}
|
||||||
|
|
||||||
|
path_iterator = paths.find("ramindex");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".ramIndex";
|
||||||
|
}
|
||||||
|
|
||||||
|
path_iterator = paths.find("fileindex");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".fileIndex";
|
||||||
|
}
|
||||||
|
|
||||||
|
path_iterator = paths.find("namesdata");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".names";
|
||||||
|
}
|
||||||
|
|
||||||
|
path_iterator = paths.find("timestamp");
|
||||||
|
if(
|
||||||
|
path_iterator != paths.end() &&
|
||||||
|
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||||
|
) {
|
||||||
|
path_iterator->second = base_string + ".timestamp";
|
||||||
}
|
}
|
||||||
paths["hsgrdata"] = std::string( paths["base"].string()) + ".hsgr";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!option_variables.count("nodesdata")) {
|
if( 1 > requested_num_threads ) {
|
||||||
if(!option_variables.count("base")) {
|
|
||||||
throw OSRMException("nodesdata (or base) must be specified");
|
|
||||||
}
|
|
||||||
paths["nodesdata"] = std::string( paths["base"].c_str()) + ".nodes";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!option_variables.count("edgesdata")) {
|
|
||||||
if(!option_variables.count("base")) {
|
|
||||||
throw OSRMException("edgesdata (or base) must be specified");
|
|
||||||
}
|
|
||||||
paths["edgesdata"] = std::string( paths["base"].c_str()) + ".edges";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!option_variables.count("ramindex")) {
|
|
||||||
if(!option_variables.count("base")) {
|
|
||||||
throw OSRMException("ramindex (or base) must be specified");
|
|
||||||
}
|
|
||||||
paths["ramindex"] = std::string( paths["base"].c_str()) + ".ramIndex";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!option_variables.count("fileindex")) {
|
|
||||||
if(!option_variables.count("base")) {
|
|
||||||
throw OSRMException("fileindex (or base) must be specified");
|
|
||||||
}
|
|
||||||
paths["fileindex"] = std::string( paths["base"].c_str()) + ".fileIndex";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!option_variables.count("namesdata")) {
|
|
||||||
if(!option_variables.count("base")) {
|
|
||||||
throw OSRMException("namesdata (or base) must be specified");
|
|
||||||
}
|
|
||||||
paths["namesdata"] = std::string( paths["base"].c_str()) + ".names";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!option_variables.count("timestamp")) {
|
|
||||||
if(!option_variables.count("base")) {
|
|
||||||
throw OSRMException("timestamp (or base) must be specified");
|
|
||||||
}
|
|
||||||
paths["timestamp"] = std::string( paths["base"].c_str()) + ".timestamp";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(1 > requested_num_threads) {
|
|
||||||
throw OSRMException("Number of threads must be a positive number");
|
throw OSRMException("Number of threads must be a positive number");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
+10
-3
@@ -37,6 +37,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
enum LogLevel { logINFO, logWARNING, logDEBUG };
|
enum LogLevel { logINFO, logWARNING, logDEBUG };
|
||||||
static boost::mutex logger_mutex;
|
static boost::mutex logger_mutex;
|
||||||
|
const char COL_RESET[] = "\x1b[0m";
|
||||||
|
const char RED[] = "\x1b[31m";
|
||||||
|
const char GREEN[] = "\x1b[32m";
|
||||||
|
const char YELLOW[] = "\x1b[33m";
|
||||||
|
const char BLUE[] = "\x1b[34m";
|
||||||
|
const char MAGENTA[] = "\x1b[35m";
|
||||||
|
const char CYAN[] = "\x1b[36m";
|
||||||
|
|
||||||
class LogPolicy : boost::noncopyable {
|
class LogPolicy : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
@@ -97,14 +104,14 @@ public:
|
|||||||
if(!LogPolicy::GetInstance().IsMute()) {
|
if(!LogPolicy::GetInstance().IsMute()) {
|
||||||
switch(level) {
|
switch(level) {
|
||||||
case logINFO:
|
case logINFO:
|
||||||
std::cout << os.str() << std::endl;
|
std::cout << os.str() << COL_RESET << std::endl;
|
||||||
break;
|
break;
|
||||||
case logWARNING:
|
case logWARNING:
|
||||||
std::cerr << os.str() << std::endl;
|
std::cerr << RED << os.str() << COL_RESET << std::endl;
|
||||||
break;
|
break;
|
||||||
case logDEBUG:
|
case logDEBUG:
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
std::cout << os.str() << std::endl;
|
std::cout << YELLOW << os.str() << COL_RESET << std::endl;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
+18
-4
@@ -132,7 +132,10 @@ static inline void doubleToString(const double value, std::string & output){
|
|||||||
boost::spirit::karma::generate(sink, boost::spirit::karma::double_, value);
|
boost::spirit::karma::generate(sink, boost::spirit::karma::double_, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string & output){
|
static inline void doubleToStringWithTwoDigitsBehindComma(
|
||||||
|
const double value,
|
||||||
|
std::string & output
|
||||||
|
){
|
||||||
// The largest 32-bit integer is 4294967295, that is 10 chars
|
// The largest 32-bit integer is 4294967295, that is 10 chars
|
||||||
// On the safe side, add 1 for sign, and 1 for trailing zero
|
// On the safe side, add 1 for sign, and 1 for trailing zero
|
||||||
char buffer[12] ;
|
char buffer[12] ;
|
||||||
@@ -140,11 +143,19 @@ static inline void doubleToStringWithTwoDigitsBehindComma(const double value, st
|
|||||||
output = buffer ;
|
output = buffer ;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void replaceAll(std::string &s, const std::string &sub, const std::string &other) {
|
inline void replaceAll(
|
||||||
|
std::string & s,
|
||||||
|
const std::string & sub,
|
||||||
|
const std::string & other
|
||||||
|
) {
|
||||||
boost::replace_all(s, sub, other);
|
boost::replace_all(s, sub, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void stringSplit(const std::string &s, const char delim, std::vector<std::string>& result) {
|
inline void stringSplit(
|
||||||
|
const std::string &s,
|
||||||
|
const char delim,
|
||||||
|
std::vector<std::string>& result
|
||||||
|
) {
|
||||||
boost::split(result, s, boost::is_any_of(std::string(&delim)));
|
boost::split(result, s, boost::is_any_of(std::string(&delim)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +177,10 @@ inline std::string HTMLDeEntitize( std::string & result) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool StringStartsWith(const std::string & input, const std::string & prefix) {
|
inline bool StringStartsWith(
|
||||||
|
const std::string & input,
|
||||||
|
const std::string & prefix
|
||||||
|
) {
|
||||||
return boost::starts_with(input, prefix);
|
return boost::starts_with(input, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-12
@@ -30,13 +30,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#cmakedefine01 HAS64BITS
|
#cmakedefine01 HAS64BITS
|
||||||
#cmakedefine MD5PREPARE "${MD5PREPARE}"
|
#cmakedefine MD5PREPARE "${MD5PREPARE}"
|
||||||
#cmakedefine MD5RTREE "${MD5RTREE}"
|
#cmakedefine MD5RTREE "${MD5RTREE}"
|
||||||
#cmakedefine MD5NODEINFO "${MD5NODEINFO}"
|
|
||||||
#cmakedefine MD5GRAPH "${MD5GRAPH}"
|
#cmakedefine MD5GRAPH "${MD5GRAPH}"
|
||||||
#cmakedefine MD5OBJECTS "${MD5OBJECTS}"
|
#cmakedefine MD5OBJECTS "${MD5OBJECTS}"
|
||||||
|
|
||||||
UUID::UUID() : magic_number(1297240911) {
|
UUID::UUID() : magic_number(1297240911) {
|
||||||
md5_prepare[32] = md5_tree[32] = md5_nodeinfo[32] = md5_graph[32] =
|
md5_prepare[32] =
|
||||||
md5_objects[32] = '\0';
|
md5_tree[32] =
|
||||||
|
md5_graph[32] =
|
||||||
|
md5_objects[32] = '\0';
|
||||||
|
|
||||||
boost::uuids::name_generator gen(named_uuid);
|
boost::uuids::name_generator gen(named_uuid);
|
||||||
std::string temp_string(__DATE__);
|
std::string temp_string(__DATE__);
|
||||||
@@ -46,8 +47,6 @@ UUID::UUID() : magic_number(1297240911) {
|
|||||||
temp_string += md5_prepare;
|
temp_string += md5_prepare;
|
||||||
std::copy(MD5RTREE, MD5RTREE+32, md5_tree);
|
std::copy(MD5RTREE, MD5RTREE+32, md5_tree);
|
||||||
temp_string += md5_tree;
|
temp_string += md5_tree;
|
||||||
std::copy(MD5NODEINFO, MD5NODEINFO+32, md5_nodeinfo);
|
|
||||||
temp_string += md5_nodeinfo;
|
|
||||||
std::copy(MD5GRAPH, MD5GRAPH+32, md5_graph);
|
std::copy(MD5GRAPH, MD5GRAPH+32, md5_graph);
|
||||||
temp_string += md5_graph;
|
temp_string += md5_graph;
|
||||||
std::copy(MD5OBJECTS, MD5OBJECTS+32, md5_objects);
|
std::copy(MD5OBJECTS, MD5OBJECTS+32, md5_objects);
|
||||||
@@ -90,13 +89,6 @@ bool UUID::TestRTree(const UUID & other) const {
|
|||||||
return std::equal(md5_tree, md5_tree+32, other.md5_tree);
|
return std::equal(md5_tree, md5_tree+32, other.md5_tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UUID::TestNodeInfo(const UUID & other) const {
|
|
||||||
if(!other.IsMagicNumberOK()) {
|
|
||||||
throw OSRMException("nodes file misses magic number. Check or reprocess the file");
|
|
||||||
}
|
|
||||||
return std::equal(md5_nodeinfo, md5_nodeinfo+32, other.md5_nodeinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UUID::TestQueryObjects(const UUID & other) const {
|
bool UUID::TestQueryObjects(const UUID & other) const {
|
||||||
if(!other.IsMagicNumberOK()) {
|
if(!other.IsMagicNumberOK()) {
|
||||||
throw OSRMException("missing magic number. Check or reprocess the file");
|
throw OSRMException("missing magic number. Check or reprocess the file");
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ private:
|
|||||||
const unsigned magic_number;
|
const unsigned magic_number;
|
||||||
char md5_prepare[33];
|
char md5_prepare[33];
|
||||||
char md5_tree[33];
|
char md5_tree[33];
|
||||||
char md5_nodeinfo[33];
|
|
||||||
char md5_graph[33];
|
char md5_graph[33];
|
||||||
char md5_objects[33];
|
char md5_objects[33];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# Locate Lua library
|
||||||
|
# This module defines
|
||||||
|
# LUA52_FOUND, if false, do not try to link to Lua
|
||||||
|
# LUA_LIBRARIES
|
||||||
|
# LUA_INCLUDE_DIR, where to find lua.h
|
||||||
|
# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
|
||||||
|
#
|
||||||
|
# Note that the expected include convention is
|
||||||
|
# #include "lua.h"
|
||||||
|
# and not
|
||||||
|
# #include <lua/lua.h>
|
||||||
|
# This is because, the lua location is not standardized and may exist
|
||||||
|
# in locations other than lua/
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2007-2009 Kitware, Inc.
|
||||||
|
# Copyright 2013 for Project-OSRM, Lua5.1 => Lua5.2
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
find_path(LUA_INCLUDE_DIR lua.h
|
||||||
|
HINTS
|
||||||
|
ENV LUA_DIR
|
||||||
|
PATH_SUFFIXES include/lua52 include/lua5.2 include/lua-5.2 include/lua include
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/sw # Fink
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt/csw # Blastwave
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
find_library(LUA_LIBRARY
|
||||||
|
NAMES lua52 lua5.2 lua-5.2 lua
|
||||||
|
HINTS
|
||||||
|
ENV LUA_DIR
|
||||||
|
PATH_SUFFIXES lib
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/sw
|
||||||
|
/opt/local
|
||||||
|
/opt/csw
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
if(LUA_LIBRARY)
|
||||||
|
# include the math library for Unix
|
||||||
|
if(UNIX AND NOT APPLE AND NOT BEOS)
|
||||||
|
find_library(LUA_MATH_LIBRARY m)
|
||||||
|
set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
|
||||||
|
# For Windows and Mac, don't need to explicitly include the math library
|
||||||
|
else()
|
||||||
|
set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
|
||||||
|
file(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
|
||||||
|
|
||||||
|
string(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
|
||||||
|
unset(lua_version_str)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua52
|
||||||
|
REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
|
||||||
|
VERSION_VAR LUA_VERSION_STRING)
|
||||||
|
|
||||||
|
mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY)
|
||||||
|
|
||||||
+19
-12
@@ -1,8 +1,8 @@
|
|||||||
# Locate Lua library
|
# Locate Lua library
|
||||||
# This module defines
|
# This module defines
|
||||||
# LUAJIT_FOUND, if false, do not try to link to Lua
|
# LUAJIT_FOUND, if false, do not try to link to Lua
|
||||||
# LUAJIT_LIBRARIES
|
# LUAJIT_LIBRARIES
|
||||||
# LUAJIT_INCLUDE_DIR, where to find lua.h
|
# LUAJIT_INCLUDE_DIR, where to find lua.h
|
||||||
#
|
#
|
||||||
# Note that the expected include convention is
|
# Note that the expected include convention is
|
||||||
# #include "lua.h"
|
# #include "lua.h"
|
||||||
@@ -28,8 +28,12 @@
|
|||||||
# 2010 - modified for cronkite to find luajit instead of lua, as it was before.
|
# 2010 - modified for cronkite to find luajit instead of lua, as it was before.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
if ( NOT LuaJIT_FIND_VERSION )
|
||||||
|
MESSAGE(FATAL_ERROR "You need to specify a version of libluajit to use")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
IF( NOT LUAJIT_FIND_QUIETLY )
|
IF( NOT LUAJIT_FIND_QUIETLY )
|
||||||
MESSAGE(STATUS "Looking for LuaJIT...")
|
MESSAGE(STATUS "Looking for LuaJIT ${LuaJIT_FIND_VERSION}")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
FIND_PATH(LUAJIT_INCLUDE_DIR lua.h
|
FIND_PATH(LUAJIT_INCLUDE_DIR lua.h
|
||||||
@@ -47,8 +51,8 @@ FIND_PATH(LUAJIT_INCLUDE_DIR lua.h
|
|||||||
/opt
|
/opt
|
||||||
)
|
)
|
||||||
|
|
||||||
FIND_LIBRARY(LUAJIT_LIBRARY
|
FIND_LIBRARY(LUAJIT_LIBRARY
|
||||||
NAMES luajit-51 luajit-5.1 luajit
|
NAMES luajit-${LuaJIT_FIND_VERSION_MAJOR}${LuaJIT_FIND_VERSION_MINOR} luajit-${LuaJIT_FIND_VERSION}
|
||||||
HINTS
|
HINTS
|
||||||
$ENV{LUAJIT_DIR}
|
$ENV{LUAJIT_DIR}
|
||||||
PATH_SUFFIXES lib64 lib
|
PATH_SUFFIXES lib64 lib
|
||||||
@@ -63,6 +67,7 @@ FIND_LIBRARY(LUAJIT_LIBRARY
|
|||||||
/opt
|
/opt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
IF(LUAJIT_LIBRARY)
|
||||||
# include the math library for Unix
|
# include the math library for Unix
|
||||||
IF(UNIX AND NOT APPLE)
|
IF(UNIX AND NOT APPLE)
|
||||||
FIND_LIBRARY(LUAJIT_MATH_LIBRARY m)
|
FIND_LIBRARY(LUAJIT_MATH_LIBRARY m)
|
||||||
@@ -71,16 +76,18 @@ FIND_LIBRARY(LUAJIT_LIBRARY
|
|||||||
ELSE(UNIX AND NOT APPLE)
|
ELSE(UNIX AND NOT APPLE)
|
||||||
SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}" CACHE STRING "Lua Libraries")
|
SET( LUAJIT_LIBRARIES "${LUAJIT_LIBRARY}" CACHE STRING "Lua Libraries")
|
||||||
ENDIF(UNIX AND NOT APPLE)
|
ENDIF(UNIX AND NOT APPLE)
|
||||||
#ENDIF(LUAJIT_LIBRARY)
|
ENDIF(LUAJIT_LIBRARY)
|
||||||
|
|
||||||
INCLUDE(FindPackageHandleStandardArgs)
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
|
# handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if
|
||||||
# all listed variables are TRUE
|
# all listed variables are TRUE
|
||||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT DEFAULT_MSG LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR)
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LUAJIT DEFAULT_MSG LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR)
|
||||||
|
|
||||||
IF( NOT LUAJIT_FIND_QUIETLY )
|
IF( NOT LUAJIT_FIND_QUIETLY )
|
||||||
IF( LUAJIT_FOUND )
|
IF( LUAJIT_FOUND AND LUAJIT_LIBRARIES)
|
||||||
MESSAGE(STATUS "Found LuaJIT: ${LUAJIT_LIBRARY}" )
|
MESSAGE(STATUS "Found LuaJIT: ${LUAJIT_LIBRARY}" )
|
||||||
ENDIF()
|
MARK_AS_ADVANCED(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY)
|
||||||
|
ELSE()
|
||||||
|
SET ( LUAJIT_FOUND FALSE )
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
MARK_AS_ADVANCED(LUAJIT_INCLUDE_DIR LUAJIT_LIBRARIES LUAJIT_LIBRARY LUAJIT_MATH_LIBRARY)
|
|
||||||
|
|||||||
@@ -48,4 +48,4 @@ IF( NOT STXXL_FIND_QUIETLY )
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY)
|
MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY)
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ set(OLDFILE ${SOURCE_DIR}/Util/UUID.cpp)
|
|||||||
if (EXISTS ${OLDFILE})
|
if (EXISTS ${OLDFILE})
|
||||||
file(REMOVE_RECURSE ${OLDFILE})
|
file(REMOVE_RECURSE ${OLDFILE})
|
||||||
endif()
|
endif()
|
||||||
file(MD5 ${SOURCE_DIR}/createHierarchy.cpp MD5PREPARE)
|
file(MD5 ${SOURCE_DIR}/prepare.cpp MD5PREPARE)
|
||||||
file(MD5 ${SOURCE_DIR}/DataStructures/StaticRTree.h MD5RTREE)
|
file(MD5 ${SOURCE_DIR}/DataStructures/StaticRTree.h MD5RTREE)
|
||||||
file(MD5 ${SOURCE_DIR}/DataStructures/NodeInformationHelpDesk.h MD5NODEINFO)
|
|
||||||
file(MD5 ${SOURCE_DIR}/Util/GraphLoader.h MD5GRAPH)
|
file(MD5 ${SOURCE_DIR}/Util/GraphLoader.h MD5GRAPH)
|
||||||
file(MD5 ${SOURCE_DIR}/Server/DataStructures/QueryObjectsStorage.cpp MD5OBJECTS)
|
file(MD5 ${SOURCE_DIR}/Server/DataStructures/InternalDataFacade.h MD5OBJECTS)
|
||||||
|
|
||||||
CONFIGURE_FILE( ${SOURCE_DIR}/Util/UUID.cpp.in ${SOURCE_DIR}/Util/UUID.cpp )
|
CONFIGURE_FILE( ${SOURCE_DIR}/Util/UUID.cpp.in ${SOURCE_DIR}/Util/UUID.cpp )
|
||||||
|
|||||||
+430
@@ -0,0 +1,430 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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 "DataStructures/QueryEdge.h"
|
||||||
|
#include "DataStructures/SharedMemoryFactory.h"
|
||||||
|
#include "DataStructures/SharedMemoryVectorWrapper.h"
|
||||||
|
#include "DataStructures/StaticGraph.h"
|
||||||
|
#include "DataStructures/StaticRTree.h"
|
||||||
|
#include "Server/DataStructures/BaseDataFacade.h"
|
||||||
|
#include "Server/DataStructures/SharedDataType.h"
|
||||||
|
#include "Server/DataStructures/SharedBarriers.h"
|
||||||
|
#include "Util/BoostFileSystemFix.h"
|
||||||
|
#include "Util/ProgramOptions.h"
|
||||||
|
#include "Util/SimpleLogger.h"
|
||||||
|
#include "Util/UUID.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
int main( const int argc, const char * argv[] ) {
|
||||||
|
SharedBarriers barrier;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"Process " << argv[0] << " could not request RAM lock";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
try {
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> pending_lock(barrier.pending_update_mutex);
|
||||||
|
} catch(...) {
|
||||||
|
// hard unlock in case of any exception.
|
||||||
|
barrier.pending_update_mutex.unlock();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
|
||||||
|
|
||||||
|
bool use_shared_memory = false;
|
||||||
|
std::string ip_address;
|
||||||
|
int ip_port, requested_num_threads;
|
||||||
|
|
||||||
|
ServerPaths server_paths;
|
||||||
|
if(
|
||||||
|
!GenerateServerProgramOptions(
|
||||||
|
argc,
|
||||||
|
argv,
|
||||||
|
server_paths,
|
||||||
|
ip_address,
|
||||||
|
ip_port,
|
||||||
|
requested_num_threads,
|
||||||
|
use_shared_memory
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if( server_paths.find("hsgrdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no hsgr file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("ramindex") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no ram index file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("fileindex") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no leaf index file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("nodesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no nodes file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("edgesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no edges file given in ini file");
|
||||||
|
}
|
||||||
|
if( server_paths.find("namesdata") == server_paths.end() ) {
|
||||||
|
throw OSRMException("no names file given in ini file");
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerPaths::const_iterator paths_iterator = server_paths.find("hsgrdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path & hsgr_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("timestamp");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path & timestamp_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("ramindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path & ram_index_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("fileindex");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const std::string & file_index_file_name = paths_iterator->second.string();
|
||||||
|
paths_iterator = server_paths.find("nodesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path & nodes_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("edgesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path & edges_data_path = paths_iterator->second;
|
||||||
|
paths_iterator = server_paths.find("namesdata");
|
||||||
|
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||||
|
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||||
|
const boost::filesystem::path & names_data_path = paths_iterator->second;
|
||||||
|
|
||||||
|
|
||||||
|
// get the shared memory segment to use
|
||||||
|
bool use_first_segment = SharedMemory::RegionExists( LAYOUT_2 );
|
||||||
|
SharedDataType LAYOUT = ( use_first_segment ? LAYOUT_1 : LAYOUT_2 );
|
||||||
|
SharedDataType DATA = ( use_first_segment ? DATA_1 : DATA_2 );
|
||||||
|
|
||||||
|
// Allocate a memory layout in shared memory, deallocate previous
|
||||||
|
SharedMemory * layout_memory = SharedMemoryFactory::Get(
|
||||||
|
LAYOUT,
|
||||||
|
sizeof(SharedDataLayout)
|
||||||
|
);
|
||||||
|
SharedDataLayout * shared_layout_ptr = static_cast<SharedDataLayout *>(
|
||||||
|
layout_memory->Ptr()
|
||||||
|
);
|
||||||
|
shared_layout_ptr = new(layout_memory->Ptr()) SharedDataLayout();
|
||||||
|
|
||||||
|
std::copy(
|
||||||
|
file_index_file_name.begin(),
|
||||||
|
(file_index_file_name.length() <= 1024 ? file_index_file_name.end() : file_index_file_name.begin()+1023),
|
||||||
|
shared_layout_ptr->ram_index_file_name
|
||||||
|
);
|
||||||
|
// add zero termination
|
||||||
|
unsigned end_of_string_index = std::min(1023ul, file_index_file_name.length());
|
||||||
|
shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0';
|
||||||
|
|
||||||
|
// collect number of elements to store in shared memory object
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Collecting files sizes";
|
||||||
|
SimpleLogger().Write() << "load names from: " << names_data_path;
|
||||||
|
// number of entries in name index
|
||||||
|
boost::filesystem::ifstream name_stream(
|
||||||
|
names_data_path, std::ios::binary
|
||||||
|
);
|
||||||
|
unsigned name_index_size = 0;
|
||||||
|
name_stream.read((char *)&name_index_size, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->name_index_list_size = name_index_size;
|
||||||
|
SimpleLogger().Write() << "size: " << name_index_size;
|
||||||
|
// SimpleLogger().Write() << "name index size: " << shared_layout_ptr->name_index_list_size;
|
||||||
|
BOOST_ASSERT_MSG(0 != shared_layout_ptr->name_index_list_size, "name file broken");
|
||||||
|
|
||||||
|
unsigned number_of_chars = 0;
|
||||||
|
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->name_char_list_size = number_of_chars;
|
||||||
|
// SimpleLogger().Write() << "name char size: " << shared_layout_ptr->name_char_list_size;
|
||||||
|
|
||||||
|
//Loading information for original edges
|
||||||
|
boost::filesystem::ifstream edges_input_stream(
|
||||||
|
edges_data_path,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
unsigned number_of_original_edges = 0;
|
||||||
|
edges_input_stream.read((char*)&number_of_original_edges, sizeof(unsigned));
|
||||||
|
|
||||||
|
shared_layout_ptr->via_node_list_size = number_of_original_edges;
|
||||||
|
shared_layout_ptr->name_id_list_size = number_of_original_edges;
|
||||||
|
shared_layout_ptr->turn_instruction_list_size = number_of_original_edges;
|
||||||
|
|
||||||
|
boost::filesystem::ifstream hsgr_input_stream(
|
||||||
|
hsgr_path,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
UUID uuid_loaded, uuid_orig;
|
||||||
|
hsgr_input_stream.read((char *)&uuid_loaded, sizeof(UUID));
|
||||||
|
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
".hsgr was prepared with different build. "
|
||||||
|
"Reprocess to get rid of this warning.";
|
||||||
|
} else {
|
||||||
|
SimpleLogger().Write(logDEBUG) << "UUID checked out ok";
|
||||||
|
}
|
||||||
|
|
||||||
|
// load checksum
|
||||||
|
unsigned checksum = 0;
|
||||||
|
hsgr_input_stream.read((char*)&checksum, sizeof(unsigned) );
|
||||||
|
shared_layout_ptr->checksum = checksum;
|
||||||
|
// load graph node size
|
||||||
|
unsigned number_of_graph_nodes = 0;
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char*) &number_of_graph_nodes,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
(0 != number_of_graph_nodes),
|
||||||
|
"number of nodes is zero"
|
||||||
|
);
|
||||||
|
shared_layout_ptr->graph_node_list_size = number_of_graph_nodes;
|
||||||
|
|
||||||
|
// load graph edge size
|
||||||
|
unsigned number_of_graph_edges = 0;
|
||||||
|
hsgr_input_stream.read( (char*) &number_of_graph_edges, sizeof(unsigned) );
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 != number_of_graph_edges,
|
||||||
|
"number of graph edges is zero"
|
||||||
|
);
|
||||||
|
shared_layout_ptr->graph_edge_list_size = number_of_graph_edges;
|
||||||
|
|
||||||
|
// load rsearch tree size
|
||||||
|
boost::filesystem::ifstream tree_node_file(
|
||||||
|
ram_index_path,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
uint32_t tree_size = 0;
|
||||||
|
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
|
||||||
|
shared_layout_ptr->r_search_tree_size = tree_size;
|
||||||
|
|
||||||
|
//load timestamp size
|
||||||
|
std::string m_timestamp;
|
||||||
|
if( boost::filesystem::exists(timestamp_path) ) {
|
||||||
|
boost::filesystem::ifstream timestampInStream( timestamp_path );
|
||||||
|
if(!timestampInStream) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
timestamp_path << " not found. setting to default";
|
||||||
|
} else {
|
||||||
|
getline(timestampInStream, m_timestamp);
|
||||||
|
timestampInStream.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m_timestamp.empty()) {
|
||||||
|
m_timestamp = "n/a";
|
||||||
|
}
|
||||||
|
if(25 < m_timestamp.length()) {
|
||||||
|
m_timestamp.resize(25);
|
||||||
|
}
|
||||||
|
shared_layout_ptr->timestamp_length = m_timestamp.length();
|
||||||
|
|
||||||
|
//load coordinate size
|
||||||
|
boost::filesystem::ifstream nodes_input_stream(
|
||||||
|
nodes_data_path,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
unsigned coordinate_list_size = 0;
|
||||||
|
nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned));
|
||||||
|
shared_layout_ptr->coordinate_list_size = coordinate_list_size;
|
||||||
|
|
||||||
|
|
||||||
|
// allocate shared memory block
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes";
|
||||||
|
SharedMemory * shared_memory = SharedMemoryFactory::Get(
|
||||||
|
DATA,
|
||||||
|
shared_layout_ptr->GetSizeOfLayout()
|
||||||
|
);
|
||||||
|
char * shared_memory_ptr = static_cast<char *>(shared_memory->Ptr());
|
||||||
|
|
||||||
|
// read actual data into shared memory object //
|
||||||
|
// Loading street names
|
||||||
|
// SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string();
|
||||||
|
unsigned * name_index_ptr = (unsigned*)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset()
|
||||||
|
);
|
||||||
|
// SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned);
|
||||||
|
|
||||||
|
name_stream.read(
|
||||||
|
(char*)name_index_ptr,
|
||||||
|
shared_layout_ptr->name_index_list_size*sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
char * name_char_ptr = shared_memory_ptr + shared_layout_ptr->GetNameListOffset();
|
||||||
|
name_stream.read(
|
||||||
|
name_char_ptr,
|
||||||
|
shared_layout_ptr->name_char_list_size*sizeof(char)
|
||||||
|
);
|
||||||
|
name_stream.close();
|
||||||
|
|
||||||
|
//load original edge information
|
||||||
|
NodeID * via_node_ptr = (NodeID *)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetViaNodeListOffset()
|
||||||
|
);
|
||||||
|
|
||||||
|
unsigned * name_id_ptr = (unsigned *)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetNameIDListOffset()
|
||||||
|
);
|
||||||
|
|
||||||
|
TurnInstruction * turn_instructions_ptr = (TurnInstruction *)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset()
|
||||||
|
);
|
||||||
|
|
||||||
|
OriginalEdgeData current_edge_data;
|
||||||
|
for(unsigned i = 0; i < number_of_original_edges; ++i) {
|
||||||
|
// SimpleLogger().Write() << i << "/" << number_of_edges;
|
||||||
|
edges_input_stream.read(
|
||||||
|
(char*)&(current_edge_data),
|
||||||
|
sizeof(OriginalEdgeData)
|
||||||
|
);
|
||||||
|
via_node_ptr[i] = current_edge_data.viaNode;
|
||||||
|
name_id_ptr[i] = current_edge_data.nameID;
|
||||||
|
turn_instructions_ptr[i] = current_edge_data.turnInstruction;
|
||||||
|
}
|
||||||
|
edges_input_stream.close();
|
||||||
|
|
||||||
|
// Loading list of coordinates
|
||||||
|
FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset()
|
||||||
|
);
|
||||||
|
|
||||||
|
NodeInfo current_node;
|
||||||
|
for(unsigned i = 0; i < coordinate_list_size; ++i) {
|
||||||
|
nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo));
|
||||||
|
coordinates_ptr[i] = FixedPointCoordinate(current_node.lat, current_node.lon);
|
||||||
|
}
|
||||||
|
nodes_input_stream.close();
|
||||||
|
|
||||||
|
//store timestamp
|
||||||
|
char * timestamp_ptr = static_cast<char *>(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetTimeStampOffset()
|
||||||
|
);
|
||||||
|
std::copy(
|
||||||
|
m_timestamp.c_str(),
|
||||||
|
m_timestamp.c_str()+m_timestamp.length(),
|
||||||
|
timestamp_ptr
|
||||||
|
);
|
||||||
|
|
||||||
|
// store search tree portion of rtree
|
||||||
|
char * rtree_ptr = static_cast<char *>(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetRSearchTreeOffset()
|
||||||
|
);
|
||||||
|
|
||||||
|
tree_node_file.read(rtree_ptr, sizeof(RTreeNode)*tree_size);
|
||||||
|
tree_node_file.close();
|
||||||
|
|
||||||
|
// load the nodes of the search graph
|
||||||
|
QueryGraph::_StrNode * graph_node_list_ptr = (QueryGraph::_StrNode*)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetGraphNodeListOffset()
|
||||||
|
);
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char*) graph_node_list_ptr,
|
||||||
|
shared_layout_ptr->graph_node_list_size*sizeof(QueryGraph::_StrNode)
|
||||||
|
);
|
||||||
|
|
||||||
|
// load the edges of the search graph
|
||||||
|
QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)(
|
||||||
|
shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett()
|
||||||
|
);
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char*) graph_edge_list_ptr,
|
||||||
|
shared_layout_ptr->graph_edge_list_size*sizeof(QueryGraph::_StrEdge)
|
||||||
|
);
|
||||||
|
hsgr_input_stream.close();
|
||||||
|
|
||||||
|
//TODO acquire lock
|
||||||
|
SharedMemory * data_type_memory = SharedMemoryFactory::Get(
|
||||||
|
CURRENT_REGIONS,
|
||||||
|
sizeof(SharedDataTimestamp),
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
SharedDataTimestamp * data_timestamp_ptr = static_cast<SharedDataTimestamp*>(
|
||||||
|
data_type_memory->Ptr()
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::interprocess::scoped_lock<
|
||||||
|
boost::interprocess::named_mutex
|
||||||
|
> query_lock(barrier.query_mutex);
|
||||||
|
|
||||||
|
// notify all processes that were waiting for this condition
|
||||||
|
if (0 < barrier.number_of_queries) {
|
||||||
|
barrier.no_running_queries_condition.wait(query_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
data_timestamp_ptr->layout = LAYOUT;
|
||||||
|
data_timestamp_ptr->data = DATA;
|
||||||
|
data_timestamp_ptr->timestamp +=1;
|
||||||
|
if(use_first_segment) {
|
||||||
|
BOOST_ASSERT( DATA == DATA_1 );
|
||||||
|
BOOST_ASSERT( LAYOUT == LAYOUT_1 );
|
||||||
|
if( !SharedMemory::Remove(DATA_2) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) << "could not delete DATA_2";
|
||||||
|
}
|
||||||
|
if( !SharedMemory::Remove(LAYOUT_2) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_2";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BOOST_ASSERT( DATA == DATA_2 );
|
||||||
|
BOOST_ASSERT( LAYOUT == LAYOUT_2 );
|
||||||
|
if( !SharedMemory::Remove(DATA_1) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) << "could not delete DATA_1";
|
||||||
|
}
|
||||||
|
if( !SharedMemory::Remove(LAYOUT_1) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) << "could not delete LAYOUT_1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimpleLogger().Write() << "all data loaded";
|
||||||
|
} catch(const std::exception & e) {
|
||||||
|
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+1
-7
@@ -169,12 +169,6 @@ int main (int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned amountOfRAM = 1;
|
|
||||||
unsigned installedRAM = GetPhysicalmemory();
|
|
||||||
if(installedRAM < 2048264) {
|
|
||||||
SimpleLogger().Write(logWARNING) << "Machine has less than 2GB RAM.";
|
|
||||||
}
|
|
||||||
|
|
||||||
StringMap stringMap;
|
StringMap stringMap;
|
||||||
ExtractionContainers externalMemory;
|
ExtractionContainers externalMemory;
|
||||||
|
|
||||||
@@ -197,7 +191,7 @@ int main (int argc, char *argv[]) {
|
|||||||
(get_timestamp() - parsing_start_time) <<
|
(get_timestamp() - parsing_start_time) <<
|
||||||
" seconds";
|
" seconds";
|
||||||
|
|
||||||
externalMemory.PrepareData(output_file_name, restrictionsFileName, amountOfRAM);
|
externalMemory.PrepareData(output_file_name, restrictionsFileName);
|
||||||
|
|
||||||
delete parser;
|
delete parser;
|
||||||
delete extractCallBacks;
|
delete extractCallBacks;
|
||||||
|
|||||||
@@ -236,18 +236,13 @@ int main (int argc, char *argv[]) {
|
|||||||
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
||||||
in.close();
|
in.close();
|
||||||
SimpleLogger().Write() <<
|
SimpleLogger().Write() <<
|
||||||
inputRestrictions.size() <<
|
inputRestrictions.size() << " restrictions, " <<
|
||||||
" restrictions, " <<
|
bollardNodes.size() << " bollard nodes, " <<
|
||||||
bollardNodes.size() <<
|
trafficLightNodes.size() << " traffic lights";
|
||||||
" bollard nodes, " <<
|
|
||||||
trafficLightNodes.size() <<
|
|
||||||
" traffic lights";
|
|
||||||
|
|
||||||
if(0 == edgeList.size()) {
|
if( edgeList.empty() ) {
|
||||||
std::cerr <<
|
SimpleLogger().Write(logWARNING) << "The input data is broken. "
|
||||||
"The input data is broken. "
|
"It is impossible to do any turns in this graph";
|
||||||
"It is impossible to do any turns in this graph" <<
|
|
||||||
std::endl;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +260,7 @@ int main (int argc, char *argv[]) {
|
|||||||
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
|
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
|
||||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
|
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
|
||||||
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
|
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
|
||||||
std::vector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
|
std::vector<EdgeBasedNode> nodeBasedEdgeList;
|
||||||
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
|
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
|
||||||
delete edgeBasedGraphFactory;
|
delete edgeBasedGraphFactory;
|
||||||
|
|
||||||
@@ -275,7 +270,12 @@ int main (int argc, char *argv[]) {
|
|||||||
|
|
||||||
SimpleLogger().Write() << "writing node map ...";
|
SimpleLogger().Write() << "writing node map ...";
|
||||||
std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
|
std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
|
||||||
mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
|
const unsigned size_of_mapping = internalToExternalNodeMapping.size();
|
||||||
|
mapOutFile.write((char *)&size_of_mapping, sizeof(unsigned));
|
||||||
|
mapOutFile.write(
|
||||||
|
(char *)&(internalToExternalNodeMapping[0]),
|
||||||
|
size_of_mapping*sizeof(NodeInfo)
|
||||||
|
);
|
||||||
mapOutFile.close();
|
mapOutFile.close();
|
||||||
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
|
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
|
||||||
|
|
||||||
@@ -286,14 +286,14 @@ int main (int argc, char *argv[]) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SimpleLogger().Write() << "building r-tree ...";
|
SimpleLogger().Write() << "building r-tree ...";
|
||||||
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * rtree =
|
StaticRTree<EdgeBasedNode> * rtree =
|
||||||
new StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode>(
|
new StaticRTree<EdgeBasedNode>(
|
||||||
nodeBasedEdgeList,
|
nodeBasedEdgeList,
|
||||||
rtree_nodes_path.c_str(),
|
rtree_nodes_path.c_str(),
|
||||||
rtree_leafs_path.c_str()
|
rtree_leafs_path.c_str()
|
||||||
);
|
);
|
||||||
delete rtree;
|
delete rtree;
|
||||||
IteratorbasedCRC32<std::vector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
|
IteratorbasedCRC32<std::vector<EdgeBasedNode> > crc32;
|
||||||
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
|
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
|
||||||
nodeBasedEdgeList.clear();
|
nodeBasedEdgeList.clear();
|
||||||
SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList;
|
SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList;
|
||||||
@@ -346,20 +346,31 @@ int main (int argc, char *argv[]) {
|
|||||||
|
|
||||||
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
||||||
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
||||||
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
|
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
|
||||||
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
|
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
|
||||||
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
|
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
|
||||||
++edge;
|
++edge;
|
||||||
_nodes[node].firstEdge = position; //=edge
|
_nodes[node].firstEdge = position; //=edge
|
||||||
position += edge - lastEdge; //remove
|
position += edge - lastEdge; //remove
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_nodes.back().firstEdge = numberOfEdges; //sentinel element
|
||||||
++numberOfNodes;
|
++numberOfNodes;
|
||||||
//Serialize numberOfNodes, nodes
|
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
_nodes.size() == numberOfNodes,
|
||||||
|
"no. of nodes dont match"
|
||||||
|
);
|
||||||
|
|
||||||
|
//serialize crc32, aka checksum
|
||||||
hsgr_output_stream.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
|
hsgr_output_stream.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
|
||||||
|
//serialize number f nodes
|
||||||
hsgr_output_stream.write((char*) &numberOfNodes, sizeof(unsigned));
|
hsgr_output_stream.write((char*) &numberOfNodes, sizeof(unsigned));
|
||||||
hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
|
//serialize number of edges
|
||||||
//Serialize number of Edges
|
|
||||||
hsgr_output_stream.write((char*) &position, sizeof(unsigned));
|
hsgr_output_stream.write((char*) &position, sizeof(unsigned));
|
||||||
|
//serialize all nodes
|
||||||
|
hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
|
||||||
|
//serialize all edges
|
||||||
--numberOfNodes;
|
--numberOfNodes;
|
||||||
edge = 0;
|
edge = 0;
|
||||||
int usedEdgeCounter = 0;
|
int usedEdgeCounter = 0;
|
||||||
+11
-2
@@ -3,7 +3,7 @@ require("lib/access")
|
|||||||
|
|
||||||
barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true}
|
barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true, ["entrance"] = true}
|
||||||
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true }
|
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true }
|
||||||
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
|
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true, ["emergency"] = true }
|
||||||
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
|
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
|
||||||
access_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
access_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
||||||
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
|
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
|
||||||
@@ -101,6 +101,16 @@ function way_function (way)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local impassable = way.tags:Find("impassable")
|
||||||
|
if "yes" == impassable then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local status = way.tags:Find("status")
|
||||||
|
if "impassable" == status then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if we are allowed to access the way
|
-- Check if we are allowed to access the way
|
||||||
local access = Access.find_access_tag(way, access_tags_hierachy)
|
local access = Access.find_access_tag(way, access_tags_hierachy)
|
||||||
if access_tag_blacklist[access] then
|
if access_tag_blacklist[access] then
|
||||||
@@ -121,7 +131,6 @@ function way_function (way)
|
|||||||
local duration = way.tags:Find("duration")
|
local duration = way.tags:Find("duration")
|
||||||
local service = way.tags:Find("service")
|
local service = way.tags:Find("service")
|
||||||
|
|
||||||
|
|
||||||
-- Set the name that will be used for instructions
|
-- Set the name that will be used for instructions
|
||||||
if "" ~= ref then
|
if "" ~= ref then
|
||||||
way.name = ref
|
way.name = ref
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
|
||||||
|
-- This example shows how to query external data stored in PostGIS when processing ways.
|
||||||
|
|
||||||
|
-- This profile assumes that OSM data has been imported to PostGIS using imposm to a db
|
||||||
|
-- with the name 'imposm', the default user and no password. It assumes areas with
|
||||||
|
-- landusage=* was imported to the table osm_landusages, containting the columns type and area.
|
||||||
|
-- Seee http://imposm.org/ for more info on imposm.
|
||||||
|
-- Other tools for importing OSM data to PostGIS include osm2pgsql and osmosis.
|
||||||
|
|
||||||
|
-- It uses the PostGIS function ST_DWithin() to find areas tagged with landuse=industrial
|
||||||
|
-- that are within 100 meters of the way.
|
||||||
|
-- It then slows down the routing depending on the number and size of the industrial area.
|
||||||
|
|
||||||
|
-- The end result is that routes will tend to avoid industrial area. Passing through
|
||||||
|
-- industrial areas is still possible, it's just slower, and thus avoided if a reasonable
|
||||||
|
-- alternative is found.
|
||||||
|
|
||||||
|
-- We use the osm id as the key when querying PostGIS. Be sure to add an index to the colunn
|
||||||
|
-- containing the osm id (osm_id in this case), otherwise you will suffer form very
|
||||||
|
-- bad performance. You should also have spatial indexes on the relevant gemoetry columns.
|
||||||
|
|
||||||
|
-- More info about using SQL form LUA can be found at http://www.keplerproject.org/luasql/
|
||||||
|
|
||||||
|
-- Happy routing!
|
||||||
|
|
||||||
|
|
||||||
|
-- Open PostGIS connection
|
||||||
|
lua_sql = require "luasql.postgres" -- we will connect to a postgresql database
|
||||||
|
sql_env = assert( lua_sql.postgres() )
|
||||||
|
sql_con = assert( sql_env:connect("imposm") ) -- you can add db user/password here if needed
|
||||||
|
print("PostGIS connection opened")
|
||||||
|
|
||||||
|
-- these settings are read directly by osrm
|
||||||
|
take_minimum_of_speeds = true
|
||||||
|
obey_oneway = true
|
||||||
|
obey_bollards = true
|
||||||
|
use_restrictions = true
|
||||||
|
ignore_areas = true -- future feature
|
||||||
|
traffic_signal_penalty = 7 -- seconds
|
||||||
|
u_turn_penalty = 20
|
||||||
|
|
||||||
|
-- nodes processing, called from OSRM
|
||||||
|
function node_function(node)
|
||||||
|
return 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ways processing, called from OSRM
|
||||||
|
function way_function (way)
|
||||||
|
-- only route on ways with highway=*
|
||||||
|
local highway = way.tags:Find("highway")
|
||||||
|
if (not highway or highway=='') then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Query PostGIS for industrial areas close to the way, then group by way and sum the areas.
|
||||||
|
-- We take the square root of the area to get a estimate of the length of the side of the area,
|
||||||
|
-- and thus a rough guess of how far we might be travelling along the area.
|
||||||
|
|
||||||
|
local sql_query = " " ..
|
||||||
|
"SELECT SUM(SQRT(area.area)) AS val " ..
|
||||||
|
"FROM osm_ways way " ..
|
||||||
|
"LEFT JOIN osm_landusages area ON ST_DWithin(way.geometry, area.geometry, 100) " ..
|
||||||
|
"WHERE area.type IN ('industrial') AND way.osm_id=" .. way.id .. " " ..
|
||||||
|
"GROUP BY way.id"
|
||||||
|
|
||||||
|
local cursor = assert( sql_con:execute(sql_query) ) -- execute querty
|
||||||
|
local row = cursor:fetch( {}, "a" ) -- fetch first (and only) row
|
||||||
|
way.speed = 20.0 -- default speed
|
||||||
|
if row then
|
||||||
|
local val = tonumber(row.val) -- read 'val' from row
|
||||||
|
if val > 10 then
|
||||||
|
way.speed = way.speed / math.log10( val ) -- reduce speed by amount of industry close by
|
||||||
|
end
|
||||||
|
end
|
||||||
|
cursor:close() -- done with this query
|
||||||
|
|
||||||
|
-- set other required info for this way
|
||||||
|
way.name = way.tags:Find("name")
|
||||||
|
way.direction = Way.bidirectional
|
||||||
|
way.type = 1
|
||||||
|
return 1
|
||||||
|
end
|
||||||
+33
-26
@@ -72,12 +72,13 @@ int main (int argc, const char * argv[]) {
|
|||||||
try {
|
try {
|
||||||
LogPolicy::GetInstance().Unmute();
|
LogPolicy::GetInstance().Unmute();
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if(!mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
|
||||||
SimpleLogger().Write(logWARNING) <<
|
SimpleLogger().Write(logWARNING) <<
|
||||||
"Process " << argv[0] << "could not be locked to RAM";
|
"Process " << argv[0] << " could not be locked to RAM";
|
||||||
}
|
}
|
||||||
installCrashHandler(argv[0]);
|
installCrashHandler(argv[0]);
|
||||||
#endif
|
#endif
|
||||||
|
bool use_shared_memory = false;
|
||||||
std::string ip_address;
|
std::string ip_address;
|
||||||
int ip_port, requested_num_threads;
|
int ip_port, requested_num_threads;
|
||||||
|
|
||||||
@@ -88,7 +89,8 @@ int main (int argc, const char * argv[]) {
|
|||||||
server_paths,
|
server_paths,
|
||||||
ip_address,
|
ip_address,
|
||||||
ip_port,
|
ip_port,
|
||||||
requested_num_threads
|
requested_num_threads,
|
||||||
|
use_shared_memory
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -98,27 +100,30 @@ int main (int argc, const char * argv[]) {
|
|||||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||||
"compiled at " << __DATE__ << ", " __TIME__;
|
"compiled at " << __DATE__ << ", " __TIME__;
|
||||||
|
|
||||||
SimpleLogger().Write() <<
|
if( use_shared_memory ) {
|
||||||
"HSGR file:\t" << server_paths["hsgrdata"];
|
SimpleLogger().Write(logDEBUG) << "Loading from shared memory";
|
||||||
SimpleLogger().Write() <<
|
} else {
|
||||||
"Nodes file:\t" << server_paths["nodesdata"];
|
SimpleLogger().Write() <<
|
||||||
SimpleLogger().Write() <<
|
"HSGR file:\t" << server_paths["hsgrdata"];
|
||||||
"Edges file:\t" << server_paths["edgesdata"];
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"Nodes file:\t" << server_paths["nodesdata"];
|
||||||
"RAM file:\t" << server_paths["ramindex"];
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"Edges file:\t" << server_paths["edgesdata"];
|
||||||
"Index file:\t" << server_paths["fileindex"];
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"RAM file:\t" << server_paths["ramindex"];
|
||||||
"Names file:\t" << server_paths["namesdata"];
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"Index file:\t" << server_paths["fileindex"];
|
||||||
"Timestamp file:\t" << server_paths["timestamp"];
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"Names file:\t" << server_paths["namesdata"];
|
||||||
"Threads:\t" << requested_num_threads;
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"Timestamp file:\t" << server_paths["timestamp"];
|
||||||
"IP address:\t" << ip_address;
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
SimpleLogger().Write() <<
|
"Threads:\t" << requested_num_threads;
|
||||||
"IP port:\t" << ip_port;
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"IP address:\t" << ip_address;
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"IP port:\t" << ip_port;
|
||||||
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
sigset_t new_mask;
|
sigset_t new_mask;
|
||||||
@@ -127,12 +132,13 @@ int main (int argc, const char * argv[]) {
|
|||||||
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
|
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OSRM routing_machine(server_paths);
|
OSRM routing_machine(server_paths, use_shared_memory);
|
||||||
Server * s = ServerFactory::CreateServer(
|
Server * s = ServerFactory::CreateServer(
|
||||||
ip_address,
|
ip_address,
|
||||||
ip_port,
|
ip_port,
|
||||||
requested_num_threads
|
requested_num_threads
|
||||||
);
|
);
|
||||||
|
|
||||||
s->GetRequestHandlerPtr().RegisterRoutingMachine(&routing_machine);
|
s->GetRequestHandlerPtr().RegisterRoutingMachine(&routing_machine);
|
||||||
|
|
||||||
boost::thread t(boost::bind(&Server::Run, s));
|
boost::thread t(boost::bind(&Server::Run, s));
|
||||||
@@ -159,7 +165,8 @@ int main (int argc, const char * argv[]) {
|
|||||||
std::cout << "[server] stopping threads" << std::endl;
|
std::cout << "[server] stopping threads" << std::endl;
|
||||||
|
|
||||||
if(!t.timed_join(boost::posix_time::seconds(2))) {
|
if(!t.timed_join(boost::posix_time::seconds(2))) {
|
||||||
SimpleLogger().Write(logDEBUG) << "Threads did not finish within 2 seconds. Hard abort!";
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"Threads did not finish within 2 seconds. Hard abort!";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "[server] freeing objects" << std::endl;
|
std::cout << "[server] freeing objects" << std::endl;
|
||||||
|
|||||||
Reference in New Issue
Block a user