Compare commits
423 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7980b83df | |||
| 0a0bed7ae0 | |||
| b01e30acfd | |||
| 311c50df9f | |||
| c2f9467f61 | |||
| 06c8656b9e | |||
| 4748bca8a4 | |||
| 916387748c | |||
| 216d7dcb86 | |||
| 23f2c7e6f5 | |||
| c8e0e5eca2 | |||
| 3167d3f451 | |||
| beb9c1ba74 | |||
| dcd88260e9 | |||
| 5f4f631fc5 | |||
| dc6fda03a1 | |||
| 764ad81537 | |||
| e26c41095f | |||
| d7bd78d612 | |||
| c50b4c72d7 | |||
| 124e555ed0 | |||
| aeba3aa209 | |||
| e50b5202b8 | |||
| 32c7578629 | |||
| 5bc5e0e8e9 | |||
| 7ee4692e84 | |||
| 679688705d | |||
| 83f0a2c094 | |||
| 504817058b | |||
| 45754b27de | |||
| a75ae8bbef | |||
| c3e6dc69bb | |||
| 0285bb6ea5 | |||
| a542292ce2 | |||
| 0765ebf735 | |||
| e86e8c37a8 | |||
| 149a42cc94 | |||
| 8de4613a3e | |||
| 60950c57e3 | |||
| 4727bb5c9b | |||
| 1e1e254897 | |||
| df5455121c | |||
| 0e2570b204 | |||
| f57519b909 | |||
| 088393ca12 | |||
| 375dc63db3 | |||
| 503324162f | |||
| 5445b64376 | |||
| 7fe997d38c | |||
| d7673dad7b | |||
| 44eed9282b | |||
| 0eeb94b24c | |||
| ef221e1c6c | |||
| 75cdefa4fe | |||
| a609a1c6c2 | |||
| f4906a97b9 | |||
| 21ffd441fa | |||
| a82383d78e | |||
| b405029f0f | |||
| db7d4f56b3 | |||
| 3151197471 | |||
| e06fe6935a | |||
| e7cec83a4c | |||
| e5f0ad4f0b | |||
| cabbe70e47 | |||
| b86c3681bb | |||
| 0f8239bc8e | |||
| 13f5baf608 | |||
| 4f5d7f79bd | |||
| 23899613c3 | |||
| db46a915cc | |||
| b591aa013d | |||
| c0db8b71dd | |||
| 444bf41fa4 | |||
| 54302a53e1 | |||
| 63059cfab3 | |||
| ec7d3a9885 | |||
| 960b55fd6c | |||
| 3067ba60ae | |||
| c9a756eddc | |||
| d4ea5fc74f | |||
| 92e52f1a5d | |||
| f03d1a5d27 | |||
| 8a55b706ca | |||
| 357133677a | |||
| 1b6c660a8f | |||
| f2b81ba86c | |||
| 2542112301 | |||
| a45215ddf2 | |||
| cb28b2de07 | |||
| bf0b43aa24 | |||
| 811d6deb41 | |||
| bcdd9374c7 | |||
| f70174d1d1 | |||
| 4a39a4af1c | |||
| 0367399c89 | |||
| c5db4dc15f | |||
| 31fbfa3a70 | |||
| 3515ddcfe6 | |||
| 90303d5952 | |||
| 9a02421091 | |||
| 4961b819f3 | |||
| 61c2ea9225 | |||
| f5f7269f70 | |||
| 03f1430ddc | |||
| c3dab15eb6 | |||
| a4f6ec516b | |||
| 1ca213cec6 | |||
| b782c8560c | |||
| d2e68068bf | |||
| 129a846393 | |||
| 15308931e9 | |||
| 4dffeedd1c | |||
| d0c4111429 | |||
| f579b6f971 | |||
| f5124de327 | |||
| 9ab86ae2bf | |||
| 51a7d3ff50 | |||
| 80b9afc14d | |||
| 92ae8f37ba | |||
| df1f828488 | |||
| d8c97da087 | |||
| 9d29e5d87a | |||
| bf62147802 | |||
| 34735b8aad | |||
| 932b2b9acf | |||
| 7ab4472865 | |||
| e1e79206f9 | |||
| 7ebe6de022 | |||
| b234760e92 | |||
| 3119e4b82b | |||
| 2c3f05e6f1 | |||
| c3c0c8d881 | |||
| 9de5e31a7a | |||
| dbf15c2db2 | |||
| c9c900b364 | |||
| 5c07204351 | |||
| de947d8b17 | |||
| 8cb5e68b1a | |||
| 99aef2a178 | |||
| fff1460dfb | |||
| e3b619fd54 | |||
| 29e363e7fb | |||
| c209245b0e | |||
| 4194ce3095 | |||
| a0e9f59e04 | |||
| c940c2722e | |||
| 5c84c12f40 | |||
| 1bcacfab74 | |||
| 1f5f8a76fb | |||
| cfa8b1f0dd | |||
| aecbcdd390 | |||
| 74729a372b | |||
| 63d8abe32f | |||
| 2c397bfa0b | |||
| bfef8f39b7 | |||
| 4430cbc3cb | |||
| ae20bac3c5 | |||
| d9a26c4062 | |||
| 48cb374d94 | |||
| 9d6bd91279 | |||
| 163cfda282 | |||
| 72cda375c8 | |||
| ecb4a08655 | |||
| 05c50bc64f | |||
| 747e4a7061 | |||
| 2b8b876713 | |||
| f13694b539 | |||
| 648f9c9723 | |||
| 0a6c37b726 | |||
| b43a51f912 | |||
| fa328c5a78 | |||
| 728bcc2b10 | |||
| 941903a243 | |||
| 4c8579b340 | |||
| 17416a09f1 | |||
| fdda21b114 | |||
| c75ae957f1 | |||
| 8c678126f1 | |||
| 2b0590f9bd | |||
| a31992aac7 | |||
| 829d2505e3 | |||
| df30498365 | |||
| 5d553bf9f2 | |||
| 03e3673dbb | |||
| 25b8b37f00 | |||
| 665f97e782 | |||
| 48a007febd | |||
| 155e0fada6 | |||
| fe2f1d32b5 | |||
| 2fcbb19e72 | |||
| 06a50d637a | |||
| 811b33e31a | |||
| 54c83ee940 | |||
| 7406e83dde | |||
| dc2c7d5339 | |||
| aaa25e5d48 | |||
| dd971d6b7d | |||
| c07966408b | |||
| 2557956b68 | |||
| 735260d21b | |||
| e5b0e43e18 | |||
| aa42b2494c | |||
| f057054172 | |||
| c39314c643 | |||
| ae018b759c | |||
| 556b498e06 | |||
| 19f1110421 | |||
| 6d61e950d6 | |||
| 438c6e616c | |||
| 8d2396b81f | |||
| 9588ef00a5 | |||
| 411603ea03 | |||
| 67addfdb37 | |||
| 3afcd31f61 | |||
| 7ac901cb08 | |||
| fcdee8f5d5 | |||
| a7c32dfa95 | |||
| 36f3c0f77a | |||
| dad4981a57 | |||
| df53357ef1 | |||
| 85e333127a | |||
| d52d86ae82 | |||
| f62293275f | |||
| af490bae8e | |||
| edf5a0f677 | |||
| 5eecd0a57d | |||
| 1fc11a6b06 | |||
| 3516538813 | |||
| e3af8cb2e8 | |||
| 16cd822555 | |||
| 5938368a09 | |||
| 50f865b81c | |||
| 96cd09471b | |||
| cf6c1e97bb | |||
| f557e1efb4 | |||
| 8893fd1656 | |||
| 081831e6ea | |||
| 46c3ce0e34 | |||
| 6031a45c68 | |||
| ca64887cba | |||
| 3f1d67ca4c | |||
| ff09af2812 | |||
| 2cc2c967d1 | |||
| bec4e4437d | |||
| f9abfbf68a | |||
| 53af4ee39f | |||
| af5f2f85da | |||
| ea83231da5 | |||
| c4693602ef | |||
| 3c8dd85966 | |||
| 0399022d25 | |||
| c6840496c0 | |||
| f7657280b6 | |||
| f88a4baf79 | |||
| b051f715e6 | |||
| 81a05c89e4 | |||
| cc55b016e9 | |||
| ae8e51074e | |||
| 313b93169d | |||
| db148741e9 | |||
| 1ecad20a0d | |||
| 22c5c539c2 | |||
| d59e526e1e | |||
| 94fa0047db | |||
| 26e2f9ddd1 | |||
| 23254b4f24 | |||
| 9a44f16846 | |||
| cad0069be2 | |||
| f315a013b8 | |||
| f780aa6160 | |||
| 0f03beb2b5 | |||
| 7e39c43896 | |||
| 906d28fa5d | |||
| 4d017f5d49 | |||
| 6410314b0b | |||
| 1c0202e790 | |||
| 918c978551 | |||
| 3d1a85bbea | |||
| 1a442c36e9 | |||
| a4e322f085 | |||
| 0b1d268b09 | |||
| c2be6bc019 | |||
| 9e11e832da | |||
| 348e656671 | |||
| 54cdf6d6f2 | |||
| 7c5ca8f199 | |||
| ee42d94e2d | |||
| 91baa9dfd7 | |||
| 572b176401 | |||
| 97f1dc0749 | |||
| d67ac1a708 | |||
| 2707001a3a | |||
| bb1064ac42 | |||
| 436cc692da | |||
| 76decf2e8b | |||
| ccdd0f599a | |||
| c65fed1d38 | |||
| c36ec7c95b | |||
| 305ce04284 | |||
| 034ce137a9 | |||
| 73c81a0a6c | |||
| 7544727f7a | |||
| 961a379f79 | |||
| 9ffcaa5550 | |||
| 2dbae6ce51 | |||
| f7505e8877 | |||
| c453f8e7a9 | |||
| 3a4695713d | |||
| 7d9d0878de | |||
| 26729ca482 | |||
| 405600783e | |||
| 5b5e9296b3 | |||
| dd5d520b53 | |||
| b3d517943a | |||
| 59ca59d431 | |||
| 78c92be14b | |||
| adf0c726ef | |||
| 9ecfed4e56 | |||
| 9db884f371 | |||
| e0c211085c | |||
| 555bfaf37a | |||
| bcf4af4a2f | |||
| 6a71163912 | |||
| cb2fcf4f52 | |||
| 061d78c681 | |||
| 0ffa973ec6 | |||
| 03de87c213 | |||
| 59481dd762 | |||
| 86f4aebead | |||
| a92950d234 | |||
| ccdc6f1a63 | |||
| 62cc8f456c | |||
| f7c6b9a0f7 | |||
| 01a6e3c619 | |||
| 6948d56e5d | |||
| 6373b3e49c | |||
| 91dc1b6639 | |||
| 6317b08090 | |||
| aae0547cca | |||
| 4f9c422e2f | |||
| 3595ac08f7 | |||
| 5339f440bd | |||
| 86d7442a5f | |||
| e6e5626a2c | |||
| 4a52dd1c5b | |||
| dd1302e8b1 | |||
| 7b4b7232fc | |||
| b069725df0 | |||
| aa9d8c773f | |||
| c68a03d05c | |||
| cbea651cf8 | |||
| b4ee345966 | |||
| 296e7ccb08 | |||
| 43bb53e789 | |||
| 384be58230 | |||
| 46d1a87b89 | |||
| 7c8bf18cc6 | |||
| 35255d052d | |||
| cf5c776990 | |||
| 9961172d70 | |||
| c1c46544a6 | |||
| fc24dbf9b7 | |||
| 7f311551dd | |||
| 1a6c01769e | |||
| 9da4e18099 | |||
| b19e2fbafe | |||
| 7f69857376 | |||
| a64420d700 | |||
| 2ccd3da5b3 | |||
| 845c73af73 | |||
| f7d79209dc | |||
| 0017aef89a | |||
| 7449f81ed4 | |||
| 724e96f0c1 | |||
| 8158e7f1c5 | |||
| 7d7baa70a9 | |||
| 2e3947cc6d | |||
| 54774726b2 | |||
| 2af9fcad68 | |||
| fd79e81fe5 | |||
| 2b5e110719 | |||
| 864c2d9f49 | |||
| 764fe533e8 | |||
| f1f59d770e | |||
| 950baaa9fc | |||
| 5b3aacb4b2 | |||
| d6adc56b3a | |||
| dbe1a4255c | |||
| eed20b2271 | |||
| e70adbb1cb | |||
| 06c22a478f | |||
| 565b0e97d1 | |||
| 00168cb12f | |||
| ffdaa71086 | |||
| 5de2aa1cbf | |||
| 64988ed831 | |||
| fa050ad616 | |||
| d2458f3169 | |||
| 551af0e45a | |||
| 4ac5440a4a | |||
| 7c54d4e62f | |||
| 8ab5915983 | |||
| 877865a4b1 | |||
| 7cf4d37595 | |||
| 80add9f820 | |||
| 12a35c1214 | |||
| 9379d2462e | |||
| c5e8bed1fb | |||
| 4aa7ade32c | |||
| c4ed218a7a | |||
| ff417fac01 | |||
| 0f4207f85e | |||
| f4431ed837 | |||
| 0235cf5d8e | |||
| 8fc8a4e303 | |||
| 943c15927a | |||
| 28f0782b17 | |||
| 09e331a76b | |||
| ce43b09991 | |||
| b869184c10 | |||
| 68e39b8053 | |||
| 8e023418e4 |
+17
-17
@@ -33,11 +33,10 @@ ehthumbs.db
|
|||||||
Icon?
|
Icon?
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
# SCons related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
SconsBuilder*
|
/build/
|
||||||
.scon*
|
/Util/UUID.cpp
|
||||||
.build
|
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
#########################
|
#########################
|
||||||
@@ -54,30 +53,31 @@ stxxl.errlog
|
|||||||
|
|
||||||
# compiled protobuffers #
|
# compiled protobuffers #
|
||||||
#########################
|
#########################
|
||||||
DataStructures/pbf-proto/*.pb.h
|
/DataStructures/pbf-proto/*.pb.h
|
||||||
DataStructures/pbf-proto/*.pb.cc
|
/DataStructures/pbf-proto/*.pb.cc
|
||||||
|
|
||||||
# External Libs #
|
# External Libs #
|
||||||
#################
|
#################
|
||||||
lib/
|
/lib/
|
||||||
win/lib
|
/win/lib
|
||||||
|
|
||||||
# Visual Studio Temp + build Files #
|
# Visual Studio Temp + build Files #
|
||||||
####################################
|
####################################
|
||||||
win/*.user
|
/win/*.user
|
||||||
win/*.ncb
|
/win/*.ncb
|
||||||
win/*.suo
|
/win/*.suo
|
||||||
win/Debug/
|
/win/Debug/
|
||||||
win/Release/
|
/win/Release/
|
||||||
win/bin/
|
/win/bin/
|
||||||
win/bin-debug/
|
/win/bin-debug/
|
||||||
/osrm-extract
|
/osrm-extract
|
||||||
/osrm-routed
|
/osrm-routed
|
||||||
/osrm-prepare
|
/osrm-prepare
|
||||||
|
/osrm-cli
|
||||||
/nohup.out
|
/nohup.out
|
||||||
|
|
||||||
# Sandbox folder #
|
# Sandbox folder #
|
||||||
###################
|
###################
|
||||||
sandbox/
|
/sandbox/
|
||||||
|
|
||||||
test/profile.lua
|
/test/profile.lua
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
[submodule "Docs"]
|
|
||||||
path = Docs
|
|
||||||
url = https://github.com/DennisSchiefer/Project-OSRM-Web.git
|
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
# - clang
|
||||||
|
# Make sure CMake is installed
|
||||||
|
install:
|
||||||
|
- sudo apt-get update >/dev/null
|
||||||
|
- sudo apt-get -q install build-essential git cmake pkg-config libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost-thread-dev libboost-system-dev libboost-regex-dev libboost-filesystem-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
|
||||||
|
before_script:
|
||||||
|
- sudo gem install bundler
|
||||||
|
- bundle install
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake .. $CMAKEOPTIONS
|
||||||
|
script: make
|
||||||
|
after_script:
|
||||||
|
- cd ..
|
||||||
|
- cucumber -p verify
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
- develop
|
||||||
|
env:
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
||||||
|
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
|
||||||
|
notifications:
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- irc.oftc.net#osrm
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
|
use_notice: true
|
||||||
|
skip_join: false
|
||||||
|
|
||||||
|
recipients:
|
||||||
|
- dennis@mapbox.com
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
@@ -23,9 +23,10 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef std::pair<unsigned, unsigned> BresenhamPixel;
|
typedef std::pair<unsigned, unsigned> BresenhamPixel;
|
||||||
|
|
||||||
inline void Bresenham (int x0, int y0, int x1, int y1, std::vector<BresenhamPixel> &resultList) {
|
inline void Bresenham (int x0, int y0, const int x1, int const y1, std::vector<BresenhamPixel> &resultList) {
|
||||||
int dx = std::abs(x1-x0);
|
int dx = std::abs(x1-x0);
|
||||||
int dy = std::abs(y1-y0);
|
int dy = std::abs(y1-y0);
|
||||||
int sx = (x0 < x1 ? 1 : -1);
|
int sx = (x0 < x1 ? 1 : -1);
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ CRC32::CRC32CFunctionPtr CRC32::detectBestCRC32C() {
|
|||||||
unsigned ecx = cpuid(1);
|
unsigned ecx = cpuid(1);
|
||||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
||||||
if (hasSSE42) {
|
if (hasSSE42) {
|
||||||
std::cout << "using hardware base sse computation" << std::endl;
|
SimpleLogger().Write() << "using hardware base sse computation";
|
||||||
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
return &CRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "using software base sse computation" << std::endl;
|
SimpleLogger().Write() << "using software base sse computation";
|
||||||
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
return &CRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -21,13 +21,14 @@
|
|||||||
#ifndef CRC32_H_
|
#ifndef CRC32_H_
|
||||||
#define CRC32_H_
|
#define CRC32_H_
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
class CRC32 {
|
class CRC32 {
|
||||||
private:
|
private:
|
||||||
unsigned crc;
|
unsigned crc;
|
||||||
unsigned slowcrc_table[1<<8];
|
|
||||||
|
|
||||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
||||||
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
typedef unsigned (CRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef DOUGLASPEUCKER_H_
|
#ifndef DOUGLASPEUCKER_H_
|
||||||
#define DOUGLASPEUCKER_H_
|
#define DOUGLASPEUCKER_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
|
|
||||||
/*This class object computes the bitvector of indicating generalized input points
|
/*This class object computes the bitvector of indicating generalized input points
|
||||||
* according to the (Ramer-)Douglas-Peucker algorithm.
|
* according to the (Ramer-)Douglas-Peucker algorithm.
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef ITERATORBASEDCRC32_H_
|
#ifndef ITERATORBASEDCRC32_H_
|
||||||
#define ITERATORBASEDCRC32_H_
|
#define ITERATORBASEDCRC32_H_
|
||||||
|
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@@ -30,7 +32,6 @@ class IteratorbasedCRC32 {
|
|||||||
private:
|
private:
|
||||||
typedef typename ContainerT::iterator ContainerT_iterator;
|
typedef typename ContainerT::iterator ContainerT_iterator;
|
||||||
unsigned crc;
|
unsigned crc;
|
||||||
unsigned slowcrc_table[1<<8];
|
|
||||||
|
|
||||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
||||||
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
||||||
@@ -81,10 +82,10 @@ private:
|
|||||||
unsigned ecx = cpuid(1);
|
unsigned ecx = cpuid(1);
|
||||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
||||||
if (hasSSE42) {
|
if (hasSSE42) {
|
||||||
std::cout << "using hardware base sse computation" << std::endl;
|
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||||
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "using software base sse computation" << std::endl;
|
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||||
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +95,7 @@ public:
|
|||||||
crcFunction = detectBestCRC32C();
|
crcFunction = detectBestCRC32C();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~IteratorbasedCRC32() {};
|
virtual ~IteratorbasedCRC32() { }
|
||||||
|
|
||||||
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
||||||
unsigned crc = 0;
|
unsigned crc = 0;
|
||||||
|
|||||||
+44
-18
@@ -21,6 +21,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef OBJECTTOBASE64_H_
|
#ifndef OBJECTTOBASE64_H_
|
||||||
#define OBJECTTOBASE64_H_
|
#define OBJECTTOBASE64_H_
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||||
#include <boost/archive/iterators/transform_width.hpp>
|
#include <boost/archive/iterators/transform_width.hpp>
|
||||||
@@ -28,40 +31,63 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
boost::archive::iterators::base64_from_binary<
|
boost::archive::iterators::base64_from_binary<
|
||||||
boost::archive::iterators::transform_width<string::const_iterator, 6, 8>
|
boost::archive::iterators::transform_width<const char *, 6, 8>
|
||||||
> base64_t;
|
> base64_t;
|
||||||
|
|
||||||
typedef
|
typedef
|
||||||
boost::archive::iterators::transform_width<
|
boost::archive::iterators::transform_width<
|
||||||
boost::archive::iterators::binary_from_base64<string::const_iterator>, 8, 6
|
boost::archive::iterators::binary_from_base64<
|
||||||
|
std::string::const_iterator>, 8, 6
|
||||||
> binary_t;
|
> binary_t;
|
||||||
|
|
||||||
template<class ToEncodeT>
|
template<class ObjectT>
|
||||||
static void EncodeObjectToBase64(const ToEncodeT & object, std::string& encoded) {
|
static void EncodeObjectToBase64(const ObjectT & object, std::string& encoded) {
|
||||||
encoded.clear();
|
const char * char_ptr_to_object = (const char *)&object;
|
||||||
char * pointerToOriginalObject = (char *)&object;
|
std::vector<unsigned char> data(sizeof(object));
|
||||||
encoded = std::string(base64_t(pointerToOriginalObject), base64_t(pointerToOriginalObject+sizeof(ToEncodeT)));
|
std::copy(
|
||||||
//replace "+" with "-" and "/" with "_"
|
char_ptr_to_object,
|
||||||
|
char_ptr_to_object + sizeof(ObjectT),
|
||||||
|
data.begin()
|
||||||
|
);
|
||||||
|
|
||||||
|
unsigned char number_of_padded_chars = 0; // is in {0,1,2};
|
||||||
|
while(data.size() % 3 != 0) {
|
||||||
|
++number_of_padded_chars;
|
||||||
|
data.push_back(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == data.size() % 3,
|
||||||
|
"base64 input data size is not a multiple of 3!"
|
||||||
|
);
|
||||||
|
encoded.resize(sizeof(ObjectT));
|
||||||
|
encoded.assign(
|
||||||
|
base64_t( &data[0] ),
|
||||||
|
base64_t( &data[0] + (data.size() - number_of_padded_chars) )
|
||||||
|
);
|
||||||
replaceAll(encoded, "+", "-");
|
replaceAll(encoded, "+", "-");
|
||||||
replaceAll(encoded, "/", "_");
|
replaceAll(encoded, "/", "_");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ToEncodeT>
|
template<class ObjectT>
|
||||||
static void DecodeObjectFromBase64(ToEncodeT & object, const std::string& _encoded) {
|
static void DecodeObjectFromBase64(const std::string& input, ObjectT & object) {
|
||||||
try {
|
try {
|
||||||
string encoded(_encoded);
|
std::string encoded(input);
|
||||||
//replace "-" with "+" and "_" with "/"
|
//replace "-" with "+" and "_" with "/"
|
||||||
replaceAll(encoded, "-", "+");
|
replaceAll(encoded, "-", "+");
|
||||||
replaceAll(encoded, "_", "/");
|
replaceAll(encoded, "_", "/");
|
||||||
char * pointerToDecodedObject = (char *)&object;
|
|
||||||
std::string dec(binary_t(encoded.begin()), binary_t(encoded.begin() + encoded.length() - 1));
|
std::copy (
|
||||||
std::copy ( dec.begin(), dec.end(), pointerToDecodedObject );
|
binary_t( encoded.begin() ),
|
||||||
} catch(...) {}
|
binary_t( encoded.begin() + encoded.length() - 1),
|
||||||
|
(char *)&object
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch(...) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* OBJECTTOBASE64_H_ */
|
#endif /* OBJECTTOBASE64_H_ */
|
||||||
|
|||||||
@@ -21,12 +21,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef POLYLINECOMPRESSOR_H_
|
#ifndef POLYLINECOMPRESSOR_H_
|
||||||
#define POLYLINECOMPRESSOR_H_
|
#define POLYLINECOMPRESSOR_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
//#include "../DataStructures/ExtractorStructs.h"
|
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class PolylineCompressor {
|
class PolylineCompressor {
|
||||||
private:
|
private:
|
||||||
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
|
inline void encodeVectorSignedNumber(std::vector<int> & numbers, std::string & output) const {
|
||||||
@@ -57,11 +56,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline void printEncodedString(const std::vector<SegmentInformation>& polyline, std::string &output) const {
|
inline void printEncodedString(
|
||||||
|
const std::vector<SegmentInformation> & polyline,
|
||||||
|
std::string & output
|
||||||
|
) const {
|
||||||
std::vector<int> deltaNumbers;
|
std::vector<int> deltaNumbers;
|
||||||
output += "\"";
|
output += "\"";
|
||||||
if(!polyline.empty()) {
|
if(!polyline.empty()) {
|
||||||
_Coordinate lastCoordinate = polyline[0].location;
|
FixedPointCoordinate lastCoordinate = polyline[0].location;
|
||||||
deltaNumbers.push_back( lastCoordinate.lat );
|
deltaNumbers.push_back( lastCoordinate.lat );
|
||||||
deltaNumbers.push_back( lastCoordinate.lon );
|
deltaNumbers.push_back( lastCoordinate.lon );
|
||||||
for(unsigned i = 1; i < polyline.size(); ++i) {
|
for(unsigned i = 1; i < polyline.size(); ++i) {
|
||||||
@@ -77,7 +79,7 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void printEncodedString(const std::vector<_Coordinate>& polyline, std::string &output) const {
|
inline void printEncodedString(const std::vector<FixedPointCoordinate>& polyline, std::string &output) const {
|
||||||
std::vector<int> deltaNumbers(2*polyline.size());
|
std::vector<int> deltaNumbers(2*polyline.size());
|
||||||
output += "\"";
|
output += "\"";
|
||||||
if(!polyline.empty()) {
|
if(!polyline.empty()) {
|
||||||
@@ -92,7 +94,7 @@ public:
|
|||||||
output += "\"";
|
output += "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void printUnencodedString(std::vector<_Coordinate> & polyline, std::string & output) const {
|
inline void printUnencodedString(std::vector<FixedPointCoordinate> & polyline, std::string & output) const {
|
||||||
output += "[";
|
output += "[";
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||||
|
|||||||
@@ -16,76 +16,88 @@ You should have received a copy of the GNU Affero General Public License
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
|
||||||
|
Strongly connected components using Tarjan's Algorithm
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include <gdal/gdal.h>
|
|
||||||
#include <gdal/ogrsf_frmts.h>
|
|
||||||
|
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/ImportEdge.h"
|
#include "../DataStructures/ImportEdge.h"
|
||||||
#include "../DataStructures/NodeCoords.h"
|
#include "../DataStructures/QueryNode.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/Restriction.h"
|
#include "../DataStructures/Restriction.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
|
||||||
// Strongly connected components using Tarjan's Algorithm
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <gdal.h>
|
||||||
|
#include <ogrsf_frmts.h>
|
||||||
|
#else
|
||||||
|
#include <gdal/gdal.h>
|
||||||
|
#include <gdal/ogrsf_frmts.h>
|
||||||
|
#endif
|
||||||
|
#include <cassert>
|
||||||
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class TarjanSCC {
|
class TarjanSCC {
|
||||||
private:
|
private:
|
||||||
struct _NodeBasedEdgeData {
|
|
||||||
|
struct TarjanNode {
|
||||||
|
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
|
||||||
|
unsigned index;
|
||||||
|
unsigned lowlink;
|
||||||
|
bool onStack;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TarjanEdgeData {
|
||||||
int distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
unsigned edgeBasedNodeID;
|
||||||
unsigned nameID:31;
|
unsigned nameID:31;
|
||||||
bool shortcut:1;
|
bool shortcut:1;
|
||||||
|
short type;
|
||||||
|
bool isAccessRestricted:1;
|
||||||
bool forward:1;
|
bool forward:1;
|
||||||
bool backward:1;
|
bool backward:1;
|
||||||
bool roundabout:1;
|
bool roundabout:1;
|
||||||
bool ignoreInGrid:1;
|
bool ignoreInGrid:1;
|
||||||
short type;
|
bool reversedEdge:1;
|
||||||
bool isAccessRestricted;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _EdgeBasedEdgeData {
|
struct TarjanStackFrame {
|
||||||
int distance;
|
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
|
||||||
unsigned via;
|
NodeID v;
|
||||||
unsigned nameID;
|
NodeID parent;
|
||||||
bool forward;
|
|
||||||
bool backward;
|
|
||||||
TurnInstruction turnInstruction;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
|
typedef DynamicGraph<TarjanEdgeData> TarjanDynamicGraph;
|
||||||
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
|
typedef TarjanDynamicGraph::InputEdge TarjanEdge;
|
||||||
std::vector<NodeInfo> inputNodeInfoList;
|
|
||||||
unsigned numberOfTurnRestrictions;
|
|
||||||
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
|
|
||||||
boost::unordered_map<NodeID, bool> _barrierNodes;
|
|
||||||
boost::unordered_map<NodeID, bool> _trafficLights;
|
|
||||||
|
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
typedef std::pair<NodeID, bool> RestrictionTarget;
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||||
|
|
||||||
|
std::vector<NodeInfo> inputNodeInfoList;
|
||||||
|
unsigned numberOfTurnRestrictions;
|
||||||
|
boost::shared_ptr<TarjanDynamicGraph> _nodeBasedGraph;
|
||||||
|
boost::unordered_map<NodeID, bool> _barrierNodes;
|
||||||
|
boost::unordered_map<NodeID, bool> _trafficLights;
|
||||||
|
|
||||||
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
|
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
|
||||||
RestrictionMap _restrictionMap;
|
RestrictionMap _restrictionMap;
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
struct EdgeBasedNode {
|
struct EdgeBasedNode {
|
||||||
bool operator<(const EdgeBasedNode & other) const {
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
return other.id < id;
|
return other.id < id;
|
||||||
@@ -104,25 +116,23 @@ public:
|
|||||||
bool ignoreInGrid:1;
|
bool ignoreInGrid:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
|
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
|
||||||
|
|
||||||
struct TarjanNode {
|
|
||||||
TarjanNode() : index(UINT_MAX), lowlink(UINT_MAX), onStack(false) {}
|
|
||||||
unsigned index;
|
|
||||||
unsigned lowlink;
|
|
||||||
bool onStack;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TarjanStackFrame {
|
|
||||||
explicit TarjanStackFrame(NodeID _v, NodeID p) : v(_v), parent(p) {}
|
|
||||||
NodeID v;
|
|
||||||
NodeID parent;
|
|
||||||
};
|
|
||||||
public:
|
public:
|
||||||
TarjanSCC(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()) {
|
TarjanSCC(
|
||||||
BOOST_FOREACH(_Restriction & restriction, irs) {
|
int nodes,
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
|
std::vector<NodeBasedEdge> & inputEdges,
|
||||||
|
std::vector<NodeID> & bn,
|
||||||
|
std::vector<NodeID> & tl,
|
||||||
|
std::vector<TurnRestriction> & irs,
|
||||||
|
std::vector<NodeInfo> & nI
|
||||||
|
) :
|
||||||
|
inputNodeInfoList(nI),
|
||||||
|
numberOfTurnRestrictions(irs.size())
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const TurnRestriction & restriction, irs) {
|
||||||
|
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(
|
||||||
|
restriction.fromNode, restriction.viaNode
|
||||||
|
);
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
|
||||||
if(restrIter == _restrictionMap.end()) {
|
if(restrIter == _restrictionMap.end()) {
|
||||||
@@ -140,7 +150,9 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
|
_restrictionBucketVector.at(index).push_back(
|
||||||
|
std::make_pair(restriction.toNode, restriction.flags.isOnly)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(NodeID id, bn) {
|
BOOST_FOREACH(NodeID id, bn) {
|
||||||
@@ -150,10 +162,10 @@ public:
|
|||||||
_trafficLights[id] = true;
|
_trafficLights[id] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeallocatingVector< _NodeBasedEdge > edges;
|
DeallocatingVector< TarjanEdge > edges;
|
||||||
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
||||||
|
|
||||||
_NodeBasedEdge edge;
|
TarjanEdge edge;
|
||||||
if(!i->isForward()) {
|
if(!i->isForward()) {
|
||||||
edge.source = i->target();
|
edge.source = i->target();
|
||||||
edge.target = i->source();
|
edge.target = i->source();
|
||||||
@@ -177,21 +189,28 @@ public:
|
|||||||
edge.data.type = i->type();
|
edge.data.type = i->type();
|
||||||
edge.data.isAccessRestricted = i->isAccessRestricted();
|
edge.data.isAccessRestricted = i->isAccessRestricted();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.edgeBasedNodeID = edges.size();
|
||||||
|
edge.data.reversedEdge = false;
|
||||||
edges.push_back( edge );
|
edges.push_back( edge );
|
||||||
if( edge.data.backward ) {
|
if( edge.data.backward ) {
|
||||||
std::swap( edge.source, edge.target );
|
std::swap( edge.source, edge.target );
|
||||||
edge.data.forward = i->isBackward();
|
edge.data.forward = i->isBackward();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.backward = i->isForward();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.edgeBasedNodeID = edges.size();
|
||||||
|
edge.data.reversedEdge = true;
|
||||||
edges.push_back( edge );
|
edges.push_back( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(inputEdges);
|
std::vector<NodeBasedEdge>().swap(inputEdges);
|
||||||
std::sort( edges.begin(), edges.end() );
|
std::sort( edges.begin(), edges.end() );
|
||||||
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
|
_nodeBasedGraph = boost::make_shared<TarjanDynamicGraph>( nodes, edges );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
|
//remove files from previous run if exist
|
||||||
|
DeleteFileIfExists("component.dbf");
|
||||||
|
DeleteFileIfExists("component.shx");
|
||||||
|
DeleteFileIfExists("component.shp");
|
||||||
|
|
||||||
Percent p(_nodeBasedGraph->GetNumberOfNodes());
|
Percent p(_nodeBasedGraph->GetNumberOfNodes());
|
||||||
|
|
||||||
const char *pszDriverName = "ESRI Shapefile";
|
const char *pszDriverName = "ESRI Shapefile";
|
||||||
@@ -240,7 +259,7 @@ public:
|
|||||||
bool beforeRecursion = recursionStack.top().first;
|
bool beforeRecursion = recursionStack.top().first;
|
||||||
TarjanStackFrame currentFrame = recursionStack.top().second;
|
TarjanStackFrame currentFrame = recursionStack.top().second;
|
||||||
NodeID v = currentFrame.v;
|
NodeID v = currentFrame.v;
|
||||||
// INFO("popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion");
|
// SimpleLogger().Write() << "popping node " << v << (beforeRecursion ? " before " : " after ") << "recursion";
|
||||||
recursionStack.pop();
|
recursionStack.pop();
|
||||||
|
|
||||||
if(beforeRecursion) {
|
if(beforeRecursion) {
|
||||||
@@ -253,45 +272,45 @@ public:
|
|||||||
tarjanStack.push(v);
|
tarjanStack.push(v);
|
||||||
tarjanNodes[v].onStack = true;
|
tarjanNodes[v].onStack = true;
|
||||||
++index;
|
++index;
|
||||||
// INFO("pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink);
|
// SimpleLogger().Write() << "pushing " << v << " onto tarjan stack, idx[" << v << "]=" << tarjanNodes[v].index << ", lowlink["<< v << "]=" << tarjanNodes[v].lowlink;
|
||||||
|
|
||||||
//Traverse outgoing edges
|
//Traverse outgoing edges
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
for(TarjanDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
||||||
_NodeBasedDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
|
TarjanDynamicGraph::NodeIterator vprime = _nodeBasedGraph->GetTarget(e2);
|
||||||
// INFO("traversing edge (" << v << "," << vprime << ")");
|
// SimpleLogger().Write() << "traversing edge (" << v << "," << vprime << ")";
|
||||||
if(UINT_MAX == tarjanNodes[vprime].index) {
|
if(UINT_MAX == tarjanNodes[vprime].index) {
|
||||||
|
|
||||||
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
|
recursionStack.push(std::make_pair(true,TarjanStackFrame(vprime, v)));
|
||||||
} else {
|
} else {
|
||||||
// INFO("Node " << vprime << " is already explored");
|
// SimpleLogger().Write() << "Node " << vprime << " is already explored";
|
||||||
if(tarjanNodes[vprime].onStack) {
|
if(tarjanNodes[vprime].onStack) {
|
||||||
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
|
unsigned newLowlink = std::min(tarjanNodes[v].lowlink, tarjanNodes[vprime].index);
|
||||||
// INFO("Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink);
|
// SimpleLogger().Write() << "Setting lowlink[" << v << "] from " << tarjanNodes[v].lowlink << " to " << newLowlink;
|
||||||
tarjanNodes[v].lowlink = newLowlink;
|
tarjanNodes[v].lowlink = newLowlink;
|
||||||
// } else {
|
// } else {
|
||||||
// INFO("But node " << vprime << " is not on stack");
|
// SimpleLogger().Write() << "But node " << vprime << " is not on stack";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// INFO("we are at the end of recursion and checking node " << v);
|
// SimpleLogger().Write() << "we are at the end of recursion and checking node " << v;
|
||||||
{ // setting lowlink in its own scope so it does not pollute namespace
|
{ // setting lowlink in its own scope so it does not pollute namespace
|
||||||
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
|
// NodeID parent = (UINT_MAX == tarjanNodes[v].parent ? v : tarjanNodes[v].parent );
|
||||||
// INFO("parent=" << currentFrame.parent);
|
// SimpleLogger().Write() << "parent=" << currentFrame.parent;
|
||||||
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
|
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << currentFrame.parent << "].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
|
||||||
//Note the index shift by 1 compared to the recursive version
|
//Note the index shift by 1 compared to the recursive version
|
||||||
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
|
tarjanNodes[currentFrame.parent].lowlink = std::min(tarjanNodes[currentFrame.parent].lowlink, tarjanNodes[v].lowlink);
|
||||||
// INFO("Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink);
|
// SimpleLogger().Write() << "Setting tarjanNodes[" << currentFrame.parent <<"].lowlink=" << tarjanNodes[currentFrame.parent].lowlink;
|
||||||
}
|
}
|
||||||
// INFO("tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index);
|
// SimpleLogger().Write() << "tarjanNodes[" << v << "].lowlink=" << tarjanNodes[v].lowlink << ", tarjanNodes[" << v << "].index=" << tarjanNodes[v].index;
|
||||||
|
|
||||||
//after recursion, lets do cycle checking
|
//after recursion, lets do cycle checking
|
||||||
//Check if we found a cycle. This is the bottom part of the recursion
|
//Check if we found a cycle. This is the bottom part of the recursion
|
||||||
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
|
if(tarjanNodes[v].lowlink == tarjanNodes[v].index) {
|
||||||
NodeID vprime;
|
NodeID vprime;
|
||||||
do {
|
do {
|
||||||
// INFO("identified component " << currentComponent << ": " << tarjanStack.top());
|
// SimpleLogger().Write() << "identified component " << currentComponent << ": " << tarjanStack.top();
|
||||||
vprime = tarjanStack.top(); tarjanStack.pop();
|
vprime = tarjanStack.top(); tarjanStack.pop();
|
||||||
tarjanNodes[vprime].onStack = false;
|
tarjanNodes[vprime].onStack = false;
|
||||||
componentsIndex[vprime] = currentComponent;
|
componentsIndex[vprime] = currentComponent;
|
||||||
@@ -299,7 +318,7 @@ public:
|
|||||||
} while( v != vprime);
|
} while( v != vprime);
|
||||||
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
|
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
|
||||||
if(sizeOfCurrentComponent > 1000)
|
if(sizeOfCurrentComponent > 1000)
|
||||||
INFO("large component [" << currentComponent << "]=" << sizeOfCurrentComponent);
|
SimpleLogger().Write() << "large component [" << currentComponent << "]=" << sizeOfCurrentComponent;
|
||||||
++currentComponent;
|
++currentComponent;
|
||||||
sizeOfCurrentComponent = 0;
|
sizeOfCurrentComponent = 0;
|
||||||
}
|
}
|
||||||
@@ -307,38 +326,50 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("identified: " << vectorOfComponentSizes.size() << " many components, marking small components");
|
SimpleLogger().Write() << "identified: " << vectorOfComponentSizes.size() << " many components, marking small components";
|
||||||
|
|
||||||
int singleCounter = 0;
|
int singleCounter = 0;
|
||||||
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
|
for(unsigned i = 0; i < vectorOfComponentSizes.size(); ++i){
|
||||||
if(1 == vectorOfComponentSizes[i])
|
if(1 == vectorOfComponentSizes[i])
|
||||||
++singleCounter;
|
++singleCounter;
|
||||||
}
|
}
|
||||||
INFO("identified " << singleCounter << " SCCs of size 1");
|
SimpleLogger().Write() << "identified " << singleCounter << " SCCs of size 1";
|
||||||
|
uint64_t total_network_distance = 0;
|
||||||
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
|
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
|
||||||
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
for(TarjanDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
p.printIncrement();
|
||||||
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
for(TarjanDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
||||||
|
if(_nodeBasedGraph->GetEdgeData(e1).reversedEdge) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TarjanDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
||||||
|
|
||||||
|
total_network_distance += 100*ApproximateDistance(
|
||||||
|
inputNodeInfoList[u].lat,
|
||||||
|
inputNodeInfoList[u].lon,
|
||||||
|
inputNodeInfoList[v].lat,
|
||||||
|
inputNodeInfoList[v].lon
|
||||||
|
);
|
||||||
|
|
||||||
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
|
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
|
||||||
assert(e1 != UINT_MAX);
|
assert(e1 != UINT_MAX);
|
||||||
assert(u != UINT_MAX);
|
assert(u != UINT_MAX);
|
||||||
assert(v != UINT_MAX);
|
assert(v != UINT_MAX);
|
||||||
|
|
||||||
//edges that end on bollard nodes may actually be in two distinct components
|
//edges that end on bollard nodes may actually be in two distinct components
|
||||||
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
|
if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) {
|
||||||
|
|
||||||
//INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")");
|
//INFO("(" << inputNodeInfoList[u].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[u].lon/COORDINATE_PRECISION << ") -> (" << inputNodeInfoList[v].lat/COORDINATE_PRECISION << ";" << inputNodeInfoList[v].lon/COORDINATE_PRECISION << ")");
|
||||||
OGRLineString lineString;
|
OGRLineString lineString;
|
||||||
lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.);
|
lineString.addPoint(inputNodeInfoList[u].lon/COORDINATE_PRECISION, inputNodeInfoList[u].lat/COORDINATE_PRECISION);
|
||||||
lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.);
|
lineString.addPoint(inputNodeInfoList[v].lon/COORDINATE_PRECISION, inputNodeInfoList[v].lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
OGRFeature *poFeature;
|
OGRFeature *poFeature;
|
||||||
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
|
poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
|
||||||
poFeature->SetGeometry( &lineString );
|
poFeature->SetGeometry( &lineString );
|
||||||
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
|
if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) {
|
||||||
{
|
throw OSRMException(
|
||||||
ERR( "Failed to create feature in shapefile.\n" );
|
"Failed to create feature in shapefile."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
OGRFeature::DestroyFeature( poFeature );
|
OGRFeature::DestroyFeature( poFeature );
|
||||||
}
|
}
|
||||||
@@ -348,7 +379,7 @@ public:
|
|||||||
OGRDataSource::DestroyDataSource( poDS );
|
OGRDataSource::DestroyDataSource( poDS );
|
||||||
std::vector<NodeID>().swap(vectorOfComponentSizes);
|
std::vector<NodeID>().swap(vectorOfComponentSizes);
|
||||||
std::vector<NodeID>().swap(componentsIndex);
|
std::vector<NodeID>().swap(componentsIndex);
|
||||||
|
SimpleLogger().Write() << "total network distance: " << (uint64_t)total_network_distance/100/1000. << " km";
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
unsigned CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
||||||
@@ -377,6 +408,12 @@ private:
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteFileIfExists(const std::string file_name) const {
|
||||||
|
if (boost::filesystem::exists(file_name) ) {
|
||||||
|
boost::filesystem::remove(file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
|
#endif /* STRONGLYCONNECTEDCOMPONENTS_H_ */
|
||||||
|
|||||||
+160
@@ -0,0 +1,160 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
project(OSRM)
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
TRY_RUN(SHARED_LIBRARY_PATH_TYPE SHARED_LIBRARY_PATH_INFO_COMPILED ${PROJECT_BINARY_DIR}/CMakeTmp ${PROJECT_SOURCE_DIR}/cmake/size.cpp OUTPUT_VARIABLE IS_64_SYSTEM)
|
||||||
|
if(IS_64_SYSTEM)
|
||||||
|
message(STATUS "System supports 64 bits.")
|
||||||
|
set( HAS64BITS 1 )
|
||||||
|
else(IS_64_SYSTEM)
|
||||||
|
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
|
||||||
|
set( HAS64BITS 0 )
|
||||||
|
endif(IS_64_SYSTEM)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P
|
||||||
|
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||||
|
DEPENDS
|
||||||
|
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
|
||||||
|
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||||
|
COMMENT "Configuring UUID.cpp"
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
||||||
|
|
||||||
|
set(BOOST_COMPONENTS filesystem regex system thread)
|
||||||
|
|
||||||
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
|
add_executable(osrm-extract ${ExtractorSources} )
|
||||||
|
|
||||||
|
file(GLOB PrepareGlob Contractor/*.cpp)
|
||||||
|
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
|
||||||
|
add_executable(osrm-prepare ${PrepareSources} )
|
||||||
|
|
||||||
|
add_executable(osrm-routed routed.cpp )
|
||||||
|
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||||
|
|
||||||
|
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||||
|
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||||
|
file(GLOB SearchEngineSource DataStructures/SearchEngine*.cpp)
|
||||||
|
file(GLOB ServerStructureGlob Server/DataStructures/*.cpp)
|
||||||
|
|
||||||
|
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${SearchEngineSource} ${ServerStructureGlob})
|
||||||
|
add_library(OSRM SHARED ${OSRMSources})
|
||||||
|
add_library(UUID STATIC Util/UUID.cpp)
|
||||||
|
add_dependencies( UUID UUIDConfigure )
|
||||||
|
|
||||||
|
# Check the release mode
|
||||||
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
message(STATUS "Configuring OSRM in debug mode")
|
||||||
|
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
|
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
|
||||||
|
#Configuring compilers
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
# using Clang
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
||||||
|
message(STATUS "OpenMP parallelization not available using clang++")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
# using GCC
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||||
|
# using Intel C++
|
||||||
|
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
# using Visual Studio C++
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||||
|
message("Set Architecture to x64 on OS X")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#Check Boost
|
||||||
|
set(BOOST_MIN_VERSION "1.44.0")
|
||||||
|
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
||||||
|
if (NOT Boost_FOUND)
|
||||||
|
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
|
||||||
|
endif (NOT Boost_FOUND)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
IF( APPLE )
|
||||||
|
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID )
|
||||||
|
ELSE( APPLE )
|
||||||
|
target_link_libraries( OSRM ${Boost_LIBRARIES} )
|
||||||
|
ENDIF( APPLE )
|
||||||
|
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID )
|
||||||
|
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID )
|
||||||
|
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID )
|
||||||
|
|
||||||
|
find_package ( BZip2 REQUIRED )
|
||||||
|
include_directories(${BZIP_INCLUDE_DIRS})
|
||||||
|
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
||||||
|
|
||||||
|
find_package( ZLIB REQUIRED )
|
||||||
|
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||||
|
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
|
||||||
|
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
||||||
|
|
||||||
|
find_package( Threads REQUIRED )
|
||||||
|
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
||||||
|
|
||||||
|
find_package( LuaJIT )
|
||||||
|
IF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES)
|
||||||
|
include_directories(${LUAJIT_INCLUDE_DIR})
|
||||||
|
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
|
||||||
|
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
|
||||||
|
ELSE( LUAJIT_INCLUDE_DIR )
|
||||||
|
find_package( Lua51 REQUIRED AND LUAJIT_LIBRARIES )
|
||||||
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
|
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
||||||
|
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
||||||
|
ENDIF( NOT APPLE AND LUAJIT_INCLUDE_DIR AND LUAJIT_LIBRARIES )
|
||||||
|
|
||||||
|
find_package( LibXml2 REQUIRED )
|
||||||
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
|
||||||
|
|
||||||
|
find_package( Luabind REQUIRED )
|
||||||
|
include_directories(${LUABIND_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
|
||||||
|
|
||||||
|
find_package( Protobuf REQUIRED )
|
||||||
|
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||||
|
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
|
||||||
|
|
||||||
|
find_package( STXXL REQUIRED )
|
||||||
|
include_directories(${STXXL_INCLUDE_DIR})
|
||||||
|
target_link_libraries (OSRM ${STXXL_LIBRARY})
|
||||||
|
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
|
||||||
|
|
||||||
|
find_package( OSMPBF REQUIRED )
|
||||||
|
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
||||||
|
|
||||||
|
if(WITH_TOOLS)
|
||||||
|
message("-- Activating OSRM internal tools")
|
||||||
|
find_package( GDAL )
|
||||||
|
if(GDAL_FOUND)
|
||||||
|
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
||||||
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
|
target_link_libraries(
|
||||||
|
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID
|
||||||
|
)
|
||||||
|
endif(GDAL_FOUND)
|
||||||
|
add_executable ( osrm-cli Tools/simpleclient.cpp )
|
||||||
|
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID )
|
||||||
|
endif(WITH_TOOLS)
|
||||||
@@ -1,261 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CONTRACTIONCLEANUP_H_INCLUDED
|
|
||||||
#define CONTRACTIONCLEANUP_H_INCLUDED
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
#include "Contractor.h"
|
|
||||||
|
|
||||||
class ContractionCleanup {
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct _CleanupHeapData {
|
|
||||||
NodeID parent;
|
|
||||||
_CleanupHeapData( NodeID p ) {
|
|
||||||
parent = p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _CleanupHeapData > _Heap;
|
|
||||||
|
|
||||||
struct _ThreadData {
|
|
||||||
_Heap* _heapForward;
|
|
||||||
_Heap* _heapBackward;
|
|
||||||
_ThreadData( NodeID nodes ) {
|
|
||||||
_heapBackward = new _Heap(nodes);
|
|
||||||
_heapForward = new _Heap(nodes);
|
|
||||||
}
|
|
||||||
~_ThreadData() {
|
|
||||||
delete _heapBackward;
|
|
||||||
delete _heapForward;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
struct Edge {
|
|
||||||
NodeID source;
|
|
||||||
NodeID target;
|
|
||||||
struct EdgeData {
|
|
||||||
NodeID via;
|
|
||||||
unsigned nameID;
|
|
||||||
int distance;
|
|
||||||
TurnInstruction turnInstruction;
|
|
||||||
bool shortcut:1;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
} data;
|
|
||||||
bool operator<( const Edge& right ) const {
|
|
||||||
if ( source != right.source )
|
|
||||||
return source < right.source;
|
|
||||||
return target < right.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
//sorts by source and other attributes
|
|
||||||
static bool CompareBySource( const Edge& left, const Edge& right ) {
|
|
||||||
if ( left.source != right.source )
|
|
||||||
return left.source < right.source;
|
|
||||||
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
|
|
||||||
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
|
|
||||||
if ( l != r )
|
|
||||||
return l < r;
|
|
||||||
if ( left.target != right.target )
|
|
||||||
return left.target < right.target;
|
|
||||||
return left.data.distance < right.data.distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator== ( const Edge& right ) const {
|
|
||||||
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
|
|
||||||
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
|
|
||||||
&& data.via == right.data.via && data.nameID == right.data.nameID
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ContractionCleanup( int numNodes, const std::vector< Edge >& edges ) {
|
|
||||||
_graph = edges;
|
|
||||||
_numNodes = numNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
~ContractionCleanup() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() {
|
|
||||||
RemoveUselessShortcuts();
|
|
||||||
}
|
|
||||||
|
|
||||||
template< class EdgeT >
|
|
||||||
void GetData( std::vector< EdgeT >& edges ) {
|
|
||||||
for ( int edge = 0, endEdges = ( int ) _graph.size(); edge != endEdges; ++edge ) {
|
|
||||||
if(_graph[edge].data.forward || _graph[edge].data.backward) {
|
|
||||||
EdgeT newEdge;
|
|
||||||
newEdge.source = _graph[edge].source;
|
|
||||||
newEdge.target = _graph[edge].target;
|
|
||||||
newEdge.data = _graph[edge].data;
|
|
||||||
edges.push_back( newEdge );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort( edges.begin(), edges.end() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
double _Timestamp() {
|
|
||||||
struct timeval tp;
|
|
||||||
gettimeofday(&tp, NULL);
|
|
||||||
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BuildOutgoingGraph() {
|
|
||||||
//sort edges by source
|
|
||||||
sort( _graph.begin(), _graph.end(), Edge::CompareBySource );
|
|
||||||
try {
|
|
||||||
_firstEdge.resize( _numNodes + 1 );
|
|
||||||
} catch(...) {
|
|
||||||
ERR("Not enough RAM on machine");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_firstEdge[0] = 0;
|
|
||||||
for ( NodeID i = 0, node = 0; i < ( NodeID ) _graph.size(); i++ ) {
|
|
||||||
while ( _graph[i].source != node )
|
|
||||||
_firstEdge[++node] = i;
|
|
||||||
if ( i == ( NodeID ) _graph.size() - 1 )
|
|
||||||
while ( node < _numNodes )
|
|
||||||
_firstEdge[++node] = ( int ) _graph.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveUselessShortcuts() {
|
|
||||||
int maxThreads = omp_get_max_threads();
|
|
||||||
std::vector < _ThreadData* > threadData;
|
|
||||||
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
|
||||||
threadData.push_back( new _ThreadData( _numNodes ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO("Scanning for useless shortcuts");
|
|
||||||
BuildOutgoingGraph();
|
|
||||||
/*
|
|
||||||
#pragma omp parallel for
|
|
||||||
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
|
|
||||||
//only remove shortcuts
|
|
||||||
if ( !_graph[i].data.shortcut )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( _graph[i].data.forward ) {
|
|
||||||
int result = _ComputeDistance( _graph[i].source, _graph[i].target, threadData[omp_get_thread_num()] );
|
|
||||||
if ( result < _graph[i].data.distance ) {
|
|
||||||
_graph[i].data.forward = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( _graph[i].data.backward ) {
|
|
||||||
int result = _ComputeDistance( _graph[i].target, _graph[i].source, threadData[omp_get_thread_num()] );
|
|
||||||
if ( result < _graph[i].data.distance ) {
|
|
||||||
_graph[i].data.backward = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
INFO("Removing edges");
|
|
||||||
int useful = 0;
|
|
||||||
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
|
|
||||||
if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_graph[useful] = _graph[i];
|
|
||||||
useful++;
|
|
||||||
}
|
|
||||||
INFO("Removed " << _graph.size() - useful << " useless shortcuts");
|
|
||||||
_graph.resize( useful );
|
|
||||||
|
|
||||||
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
|
|
||||||
delete threadData[threadNum];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _ComputeStep( _Heap* heapForward, _Heap* heapBackward, bool forwardDirection, NodeID* middle, int* targetDistance ) {
|
|
||||||
|
|
||||||
const NodeID node = heapForward->DeleteMin();
|
|
||||||
const int distance = heapForward->GetKey( node );
|
|
||||||
|
|
||||||
if ( distance > *targetDistance ) {
|
|
||||||
heapForward->DeleteAll();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( heapBackward->WasInserted( node ) ) {
|
|
||||||
const int newDistance = heapBackward->GetKey( node ) + distance;
|
|
||||||
if ( newDistance < *targetDistance ) {
|
|
||||||
*middle = node;
|
|
||||||
*targetDistance = newDistance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
|
|
||||||
const NodeID to = _graph[edge].target;
|
|
||||||
const int edgeWeight = _graph[edge].data.distance;
|
|
||||||
assert( edgeWeight > 0 );
|
|
||||||
const int toDistance = distance + edgeWeight;
|
|
||||||
|
|
||||||
if ( (forwardDirection ? _graph[edge].data.forward : _graph[edge].data.backward ) ) {
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
|
||||||
if ( !heapForward->WasInserted( to ) )
|
|
||||||
heapForward->Insert( to, toDistance, node );
|
|
||||||
|
|
||||||
//Found a shorter Path -> Update distance
|
|
||||||
else if ( toDistance < heapForward->GetKey( to ) ) {
|
|
||||||
heapForward->DecreaseKey( to, toDistance );
|
|
||||||
//new parent
|
|
||||||
heapForward->GetData( to ) = node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data ) {
|
|
||||||
data->_heapForward->Clear();
|
|
||||||
data->_heapBackward->Clear();
|
|
||||||
//insert source into heap
|
|
||||||
data->_heapForward->Insert( source, 0, source );
|
|
||||||
data->_heapBackward->Insert( target, 0, target );
|
|
||||||
|
|
||||||
int targetDistance = std::numeric_limits< int >::max();
|
|
||||||
NodeID middle = std::numeric_limits<NodeID>::max();
|
|
||||||
|
|
||||||
while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) {
|
|
||||||
if ( data->_heapForward->Size() > 0 ) {
|
|
||||||
_ComputeStep( data->_heapForward, data->_heapBackward, true, &middle, &targetDistance );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( data->_heapBackward->Size() > 0 ) {
|
|
||||||
_ComputeStep( data->_heapBackward, data->_heapForward, false, &middle, &targetDistance );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return targetDistance;
|
|
||||||
}
|
|
||||||
NodeID _numNodes;
|
|
||||||
std::vector< Edge > _graph;
|
|
||||||
std::vector< unsigned > _firstEdge;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CONTRACTIONCLEANUP_H_INCLUDED
|
|
||||||
+81
-55
@@ -20,17 +20,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#ifndef CONTRACTOR_H_INCLUDED
|
#ifndef CONTRACTOR_H_INCLUDED
|
||||||
#define CONTRACTOR_H_INCLUDED
|
#define CONTRACTOR_H_INCLUDED
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <cfloat>
|
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
#include "../DataStructures/BinaryHeap.h"
|
#include "../DataStructures/BinaryHeap.h"
|
||||||
@@ -40,8 +29,22 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../DataStructures/XORFastHash.h"
|
#include "../DataStructures/XORFastHash.h"
|
||||||
#include "../DataStructures/XORFastHashStorage.h"
|
#include "../DataStructures/XORFastHashStorage.h"
|
||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/lambda/lambda.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Contractor {
|
class Contractor {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -119,10 +122,11 @@ public:
|
|||||||
newEdge.target = diter->target();
|
newEdge.target = diter->target();
|
||||||
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
||||||
|
|
||||||
assert( newEdge.data.distance > 0 );
|
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
||||||
WARN("Edge weight large -> " << newEdge.data.distance);
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"Edge weight large -> " << newEdge.data.distance;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
@@ -157,11 +161,13 @@ public:
|
|||||||
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
|
forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max();
|
||||||
//remove parallel edges
|
//remove parallel edges
|
||||||
while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
|
while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) {
|
||||||
if ( edges[i].data.forward )
|
if ( edges[i].data.forward) {
|
||||||
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
|
forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance );
|
||||||
if ( edges[i].data.backward )
|
}
|
||||||
|
if ( edges[i].data.backward) {
|
||||||
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
|
backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance );
|
||||||
i++;
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
//merge edges (s,t) and (t,s) into bidirectional edge
|
//merge edges (s,t) and (t,s) into bidirectional edge
|
||||||
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
|
if ( forwardEdge.data.distance == backwardEdge.data.distance ) {
|
||||||
@@ -194,9 +200,9 @@ public:
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// INFO("edges at node with id " << highestNode << " has degree " << maxdegree);
|
// SimpleLogger().Write() << "edges at node with id " << highestNode << " has degree " << maxdegree;
|
||||||
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
|
// for(unsigned i = _graph->BeginEdges(highestNode); i < _graph->EndEdges(highestNode); ++i) {
|
||||||
// INFO(" ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via);
|
// SimpleLogger().Write() << " ->(" << highestNode << "," << _graph->GetTarget(i) << "); via: " << _graph->GetEdgeData(i).via;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//Create temporary file
|
//Create temporary file
|
||||||
@@ -230,8 +236,9 @@ public:
|
|||||||
|
|
||||||
//initialize the variables
|
//initialize the variables
|
||||||
#pragma omp parallel for schedule ( guided )
|
#pragma omp parallel for schedule ( guided )
|
||||||
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
|
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
|
||||||
remainingNodes[x].id = x;
|
remainingNodes[x].id = x;
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
std::cout << "initializing elimination PQ ..." << std::flush;
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
@@ -242,10 +249,10 @@ public:
|
|||||||
nodePriority[x] = _Evaluate( data, &nodeData[x], x );
|
nodePriority[x] = _Evaluate( data, &nodeData[x], x );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "ok" << std::endl << "preprocessing ..." << std::flush;
|
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
|
||||||
|
|
||||||
bool flushedContractor = false;
|
bool flushedContractor = false;
|
||||||
while ( numberOfContractedNodes < numberOfNodes ) {
|
while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
|
||||||
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
|
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
|
||||||
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
||||||
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
||||||
@@ -274,13 +281,12 @@ public:
|
|||||||
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
||||||
//Write dummy number of edges to temporary file
|
//Write dummy number of edges to temporary file
|
||||||
// std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
// std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
||||||
long initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
|
uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
|
||||||
unsigned numberOfTemporaryEdges = 0;
|
unsigned numberOfTemporaryEdges = 0;
|
||||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||||
|
|
||||||
//walk over all nodes
|
//walk over all nodes
|
||||||
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
||||||
//INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes());
|
|
||||||
const NodeID start = i;
|
const NodeID start = i;
|
||||||
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
|
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
|
||||||
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
|
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
|
||||||
@@ -299,8 +305,14 @@ public:
|
|||||||
newEdge.target = newNodeIDFromOldNodeIDMap[target];
|
newEdge.target = newNodeIDFromOldNodeIDMap[target];
|
||||||
newEdge.data = data;
|
newEdge.data = data;
|
||||||
newEdge.data.originalViaNodeID = true;
|
newEdge.data.originalViaNodeID = true;
|
||||||
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[start] );
|
BOOST_ASSERT_MSG(
|
||||||
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[target]);
|
UINT_MAX != newNodeIDFromOldNodeIDMap[start],
|
||||||
|
"new start id not resolveable"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
UINT_MAX != newNodeIDFromOldNodeIDMap[target],
|
||||||
|
"new target id not resolveable"
|
||||||
|
);
|
||||||
newSetOfEdges.push_back(newEdge);
|
newSetOfEdges.push_back(newEdge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,8 +321,6 @@ public:
|
|||||||
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
|
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
|
||||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||||
|
|
||||||
// INFO("Flushed " << numberOfTemporaryEdges << " edges to disk");
|
|
||||||
|
|
||||||
//Delete map from old NodeIDs to new ones.
|
//Delete map from old NodeIDs to new ones.
|
||||||
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
||||||
|
|
||||||
@@ -422,52 +432,63 @@ public:
|
|||||||
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
// avgdegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||||
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
// quaddegree /= std::max((unsigned)1,(unsigned)remainingNodes.size() );
|
||||||
//
|
//
|
||||||
// INFO("rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree);
|
// SimpleLogger().Write() << "rest: " << remainingNodes.size() << ", max: " << maxdegree << ", min: " << mindegree << ", avg: " << avgdegree << ", quad: " << quaddegree;
|
||||||
|
|
||||||
p.printStatus(numberOfContractedNodes);
|
p.printStatus(numberOfContractedNodes);
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(_ThreadData * data, threadData)
|
BOOST_FOREACH(_ThreadData * data, threadData) {
|
||||||
delete data;
|
delete data;
|
||||||
|
}
|
||||||
threadData.clear();
|
threadData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< class Edge >
|
template< class Edge >
|
||||||
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
|
inline void GetEdges( DeallocatingVector< Edge >& edges ) {
|
||||||
Percent p (_graph->GetNumberOfNodes());
|
Percent p (_graph->GetNumberOfNodes());
|
||||||
INFO("Getting edges of minimized graph");
|
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||||
if(oldNodeIDFromNewNodeIDMap.size()) {
|
if(_graph->GetNumberOfNodes()) {
|
||||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||||
p.printStatus(node);
|
p.printStatus(node);
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
||||||
const NodeID target = _graph->GetTarget( edge );
|
const NodeID target = _graph->GetTarget( edge );
|
||||||
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
||||||
Edge newEdge;
|
Edge newEdge;
|
||||||
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
|
||||||
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
||||||
assert(UINT_MAX != newEdge.source);
|
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
||||||
assert(UINT_MAX != newEdge.target);
|
} else {
|
||||||
|
newEdge.source = node;
|
||||||
|
newEdge.target = target;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
UINT_MAX != newEdge.source,
|
||||||
|
"Source id invalid"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
UINT_MAX != newEdge.target,
|
||||||
|
"Target id invalid"
|
||||||
|
);
|
||||||
newEdge.data.distance = data.distance;
|
newEdge.data.distance = data.distance;
|
||||||
newEdge.data.shortcut = data.shortcut;
|
newEdge.data.shortcut = data.shortcut;
|
||||||
if(!data.originalViaNodeID)
|
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
|
||||||
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
||||||
else
|
} else {
|
||||||
newEdge.data.id = data.id;
|
newEdge.data.id = data.id;
|
||||||
|
}
|
||||||
assert(newEdge.data.id != UINT_MAX);
|
BOOST_ASSERT_MSG(
|
||||||
|
newEdge.data.id != INT_MAX, //2^31
|
||||||
|
"edge id invalid"
|
||||||
|
);
|
||||||
newEdge.data.forward = data.forward;
|
newEdge.data.forward = data.forward;
|
||||||
newEdge.data.backward = data.backward;
|
newEdge.data.backward = data.backward;
|
||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INFO("Renumbered edges of minimized graph, freeing space");
|
|
||||||
_graph.reset();
|
_graph.reset();
|
||||||
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
||||||
INFO("Loading temporary edges");
|
|
||||||
|
|
||||||
// std::ifstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
|
||||||
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
||||||
//Also get the edges from temporary storage
|
//Also get the edges from temporary storage
|
||||||
unsigned numberOfTemporaryEdges = 0;
|
unsigned numberOfTemporaryEdges = 0;
|
||||||
@@ -492,7 +513,6 @@ public:
|
|||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
}
|
}
|
||||||
tempStorage.deallocateSlot(temporaryStorageSlotID);
|
tempStorage.deallocateSlot(temporaryStorageSlotID);
|
||||||
INFO("Hierarchy has " << edges.size() << " edges");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -515,24 +535,27 @@ private:
|
|||||||
|
|
||||||
if ( heap.GetData( node ).target ) {
|
if ( heap.GetData( node ).target ) {
|
||||||
++targetsFound;
|
++targetsFound;
|
||||||
if ( targetsFound >= numTargets )
|
if ( targetsFound >= numTargets ) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//iterate over all edges of node
|
//iterate over all edges of node
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
|
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
|
||||||
const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
|
const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
|
||||||
if ( !data.forward )
|
if ( !data.forward ){
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const NodeID to = _graph->GetTarget( edge );
|
const NodeID to = _graph->GetTarget( edge );
|
||||||
if(middleNode == to)
|
if(middleNode == to) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const int toDistance = distance + data.distance;
|
const int toDistance = distance + data.distance;
|
||||||
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !heap.WasInserted( to ) )
|
if ( !heap.WasInserted( to ) ) {
|
||||||
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
|
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
|
||||||
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < heap.GetKey( to ) ) {
|
else if ( toDistance < heap.GetKey( to ) ) {
|
||||||
heap.DecreaseKey( to, toDistance );
|
heap.DecreaseKey( to, toDistance );
|
||||||
@@ -582,8 +605,9 @@ private:
|
|||||||
|
|
||||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
||||||
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||||
if ( !outData.forward )
|
if ( !outData.forward ) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const NodeID target = _graph->GetTarget( outEdge );
|
const NodeID target = _graph->GetTarget( outEdge );
|
||||||
const int pathDistance = inData.distance + outData.distance;
|
const int pathDistance = inData.distance + outData.distance;
|
||||||
maxDistance = std::max( maxDistance, pathDistance );
|
maxDistance = std::max( maxDistance, pathDistance );
|
||||||
@@ -593,15 +617,16 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Simulate )
|
if( Simulate ) {
|
||||||
_Dijkstra( maxDistance, numTargets, 1000, data, node );
|
_Dijkstra( maxDistance, numTargets, 1000, data, node );
|
||||||
else
|
} else {
|
||||||
_Dijkstra( maxDistance, numTargets, 2000, data, node );
|
_Dijkstra( maxDistance, numTargets, 2000, data, node );
|
||||||
|
}
|
||||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
||||||
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||||
if ( !outData.forward )
|
if ( !outData.forward ) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const NodeID target = _graph->GetTarget( outEdge );
|
const NodeID target = _graph->GetTarget( outEdge );
|
||||||
const int pathDistance = inData.distance + outData.distance;
|
const int pathDistance = inData.distance + outData.distance;
|
||||||
const int distance = heap.GetKey( target );
|
const int distance = heap.GetKey( target );
|
||||||
@@ -641,8 +666,9 @@ private:
|
|||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( !found )
|
if ( !found ) {
|
||||||
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
|
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
insertedEdges.resize( insertedEdgesSize );
|
insertedEdges.resize( insertedEdgesSize );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,194 +20,262 @@
|
|||||||
|
|
||||||
#include "EdgeBasedGraphFactory.h"
|
#include "EdgeBasedGraphFactory.h"
|
||||||
|
|
||||||
template<>
|
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<NodeID> & bn, std::vector<NodeID> & tl, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI, SpeedProfileProperties sp) : inputNodeInfoList(nI), numberOfTurnRestrictions(irs.size()), speedProfile(sp) {
|
int number_of_nodes,
|
||||||
BOOST_FOREACH(_Restriction & restriction, irs) {
|
std::vector<ImportEdge> & input_edge_list,
|
||||||
std::pair<NodeID, NodeID> restrictionSource = std::make_pair(restriction.fromNode, restriction.viaNode);
|
std::vector<NodeID> & barrier_node_list,
|
||||||
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
|
std::vector<TurnRestriction> & input_restrictions_list,
|
||||||
|
std::vector<NodeInfo> & m_node_info_list,
|
||||||
|
SpeedProfileProperties speed_profile
|
||||||
|
) : speed_profile(speed_profile),
|
||||||
|
m_turn_restrictions_count(0),
|
||||||
|
m_node_info_list(m_node_info_list)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) {
|
||||||
|
std::pair<NodeID, NodeID> restriction_source =
|
||||||
|
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||||
unsigned index;
|
unsigned index;
|
||||||
RestrictionMap::iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if(restrIter == _restrictionMap.end()) {
|
if(restriction_iter == m_restriction_map.end()) {
|
||||||
index = _restrictionBucketVector.size();
|
index = m_restriction_bucket_list.size();
|
||||||
_restrictionBucketVector.resize(index+1);
|
m_restriction_bucket_list.resize(index+1);
|
||||||
_restrictionMap[restrictionSource] = index;
|
m_restriction_map[restriction_source] = index;
|
||||||
} else {
|
} else {
|
||||||
index = restrIter->second;
|
index = restriction_iter->second;
|
||||||
//Map already contains an is_only_*-restriction
|
//Map already contains an is_only_*-restriction
|
||||||
if(_restrictionBucketVector.at(index).begin()->second)
|
if(m_restriction_bucket_list.at(index).begin()->second) {
|
||||||
continue;
|
continue;
|
||||||
else if(restriction.flags.isOnly){
|
} else if(restriction.flags.isOnly) {
|
||||||
//We are going to insert an is_only_*-restriction. There can be only one.
|
//We are going to insert an is_only_*-restriction. There can be only one.
|
||||||
_restrictionBucketVector.at(index).clear();
|
m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size();
|
||||||
|
m_restriction_bucket_list.at(index).clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
++m_turn_restrictions_count;
|
||||||
_restrictionBucketVector.at(index).push_back(std::make_pair(restriction.toNode, restriction.flags.isOnly));
|
m_restriction_bucket_list.at(index).push_back(
|
||||||
|
std::make_pair( restriction.toNode, restriction.flags.isOnly)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(NodeID id, bn) {
|
m_barrier_nodes.insert(
|
||||||
_barrierNodes[id] = true;
|
barrier_node_list.begin(),
|
||||||
}
|
barrier_node_list.end()
|
||||||
BOOST_FOREACH(NodeID id, tl) {
|
);
|
||||||
_trafficLights[id] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeallocatingVector< _NodeBasedEdge > edges;
|
m_traffic_lights.insert(
|
||||||
// edges.reserve( 2 * inputEdges.size() );
|
traffic_light_node_list.begin(),
|
||||||
for ( std::vector< NodeBasedEdge >::const_iterator i = inputEdges.begin(); i != inputEdges.end(); ++i ) {
|
traffic_light_node_list.end()
|
||||||
|
);
|
||||||
|
|
||||||
_NodeBasedEdge edge;
|
DeallocatingVector< NodeBasedEdge > edges_list;
|
||||||
if(!i->isForward()) {
|
NodeBasedEdge edge;
|
||||||
edge.source = i->target();
|
BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) {
|
||||||
edge.target = i->source();
|
if(!import_edge.isForward()) {
|
||||||
edge.data.backward = i->isForward();
|
edge.source = import_edge.target();
|
||||||
edge.data.forward = i->isBackward();
|
edge.target = import_edge.source();
|
||||||
|
edge.data.backward = import_edge.isForward();
|
||||||
|
edge.data.forward = import_edge.isBackward();
|
||||||
} else {
|
} else {
|
||||||
edge.source = i->source();
|
edge.source = import_edge.source();
|
||||||
edge.target = i->target();
|
edge.target = import_edge.target();
|
||||||
edge.data.forward = i->isForward();
|
edge.data.forward = import_edge.isForward();
|
||||||
edge.data.backward = i->isBackward();
|
edge.data.backward = import_edge.isBackward();
|
||||||
}
|
}
|
||||||
if(edge.source == edge.target)
|
if(edge.source == edge.target) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
edge.data.distance = (std::max)((int)i->weight(), 1 );
|
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
|
||||||
assert( edge.data.distance > 0 );
|
assert( edge.data.distance > 0 );
|
||||||
edge.data.shortcut = false;
|
edge.data.shortcut = false;
|
||||||
edge.data.roundabout = i->isRoundabout();
|
edge.data.roundabout = import_edge.isRoundabout();
|
||||||
edge.data.ignoreInGrid = i->ignoreInGrid();
|
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
|
||||||
edge.data.nameID = i->name();
|
edge.data.nameID = import_edge.name();
|
||||||
edge.data.type = i->type();
|
edge.data.type = import_edge.type();
|
||||||
edge.data.isAccessRestricted = i->isAccessRestricted();
|
edge.data.isAccessRestricted = import_edge.isAccessRestricted();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.edgeBasedNodeID = edges_list.size();
|
||||||
edges.push_back( edge );
|
edge.data.contraFlow = import_edge.isContraFlow();
|
||||||
|
edges_list.push_back( edge );
|
||||||
if( edge.data.backward ) {
|
if( edge.data.backward ) {
|
||||||
std::swap( edge.source, edge.target );
|
std::swap( edge.source, edge.target );
|
||||||
edge.data.forward = i->isBackward();
|
edge.data.forward = import_edge.isBackward();
|
||||||
edge.data.backward = i->isForward();
|
edge.data.backward = import_edge.isForward();
|
||||||
edge.data.edgeBasedNodeID = edges.size();
|
edge.data.edgeBasedNodeID = edges_list.size();
|
||||||
edges.push_back( edge );
|
edges_list.push_back( edge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<NodeBasedEdge>().swap(inputEdges);
|
std::vector<ImportEdge>().swap(input_edge_list);
|
||||||
std::sort( edges.begin(), edges.end() );
|
std::sort( edges_list.begin(), edges_list.end() );
|
||||||
_nodeBasedGraph = boost::make_shared<_NodeBasedDynamicGraph>( nodes, edges );
|
m_node_based_graph = boost::make_shared<NodeBasedDynamicGraph>(
|
||||||
|
number_of_nodes, edges_list
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
|
void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
||||||
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
|
DeallocatingVector< EdgeBasedEdge >& output_edge_list
|
||||||
edgeBasedEdges.swap(outputEdgeList);
|
) {
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == output_edge_list.size(),
|
||||||
|
"Vector is not empty"
|
||||||
|
);
|
||||||
|
m_edge_based_edge_list.swap(output_edge_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes) {
|
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
|
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
|
||||||
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
||||||
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
|
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
nodes.swap(edgeBasedNodes);
|
nodes.swap(m_edge_based_node_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetOriginalEdgeData( std::vector< OriginalEdgeData> & oed) {
|
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
|
||||||
oed.swap(originalEdgeData);
|
const NodeID u,
|
||||||
}
|
const NodeID v
|
||||||
|
) const {
|
||||||
NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const {
|
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
if (restriction_iter != m_restriction_map.end()) {
|
||||||
if (restrIter != _restrictionMap.end()) {
|
const unsigned index = restriction_iter->second;
|
||||||
unsigned index = restrIter->second;
|
BOOST_FOREACH(
|
||||||
BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) {
|
const RestrictionSource & restriction_target,
|
||||||
if(restrictionTarget.second) {
|
m_restriction_bucket_list.at(index)
|
||||||
return restrictionTarget.first;
|
) {
|
||||||
|
if(restriction_target.second) {
|
||||||
|
return restriction_target.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const {
|
bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const {
|
||||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||||
std::pair < NodeID, NodeID > restrictionSource = std::make_pair(u, v);
|
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||||
RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource);
|
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||||
if (restrIter != _restrictionMap.end()) {
|
if (restriction_iter != m_restriction_map.end()) {
|
||||||
unsigned index = restrIter->second;
|
const unsigned index = restriction_iter->second;
|
||||||
BOOST_FOREACH(RestrictionTarget restrictionTarget, _restrictionBucketVector.at(index)) {
|
BOOST_FOREACH(
|
||||||
if(w == restrictionTarget.first)
|
const RestrictionTarget & restriction_target,
|
||||||
|
m_restriction_bucket_list.at(index)
|
||||||
|
) {
|
||||||
|
if(w == restriction_target.first) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
||||||
_NodeBasedDynamicGraph::EdgeIterator e1,
|
EdgeIterator e1,
|
||||||
_NodeBasedDynamicGraph::NodeIterator u,
|
NodeIterator u,
|
||||||
_NodeBasedDynamicGraph::NodeIterator v,
|
NodeIterator v,
|
||||||
bool belongsToTinyComponent) {
|
bool belongsToTinyComponent) {
|
||||||
_NodeBasedDynamicGraph::EdgeData & data = _nodeBasedGraph->GetEdgeData(e1);
|
EdgeData & data = m_node_based_graph->GetEdgeData(e1);
|
||||||
EdgeBasedNode currentNode;
|
EdgeBasedNode currentNode;
|
||||||
currentNode.nameID = data.nameID;
|
currentNode.nameID = data.nameID;
|
||||||
currentNode.lat1 = inputNodeInfoList[u].lat;
|
currentNode.lat1 = m_node_info_list[u].lat;
|
||||||
currentNode.lon1 = inputNodeInfoList[u].lon;
|
currentNode.lon1 = m_node_info_list[u].lon;
|
||||||
currentNode.lat2 = inputNodeInfoList[v].lat;
|
currentNode.lat2 = m_node_info_list[v].lat;
|
||||||
currentNode.lon2 = inputNodeInfoList[v].lon;
|
currentNode.lon2 = m_node_info_list[v].lon;
|
||||||
currentNode.belongsToTinyComponent = belongsToTinyComponent;
|
currentNode.belongsToTinyComponent = belongsToTinyComponent;
|
||||||
currentNode.id = data.edgeBasedNodeID;
|
currentNode.id = data.edgeBasedNodeID;
|
||||||
currentNode.ignoreInGrid = data.ignoreInGrid;
|
currentNode.ignoreInGrid = data.ignoreInGrid;
|
||||||
currentNode.weight = data.distance;
|
currentNode.weight = data.distance;
|
||||||
edgeBasedNodes.push_back(currentNode);
|
m_edge_based_node_list.push_back(currentNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
void EdgeBasedGraphFactory::Run(
|
||||||
Percent p(_nodeBasedGraph->GetNumberOfNodes());
|
const char * original_edge_data_filename,
|
||||||
int numberOfSkippedTurns(0);
|
lua_State *lua_state
|
||||||
int nodeBasedEdgeCounter(0);
|
) {
|
||||||
unsigned numberOfOriginalEdges(0);
|
SimpleLogger().Write() << "Identifying components of the road network";
|
||||||
std::ofstream originalEdgeDataOutFile(originalEdgeDataFilename, std::ios::binary);
|
|
||||||
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
|
|
||||||
|
|
||||||
|
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||||
|
unsigned skipped_turns_counter = 0;
|
||||||
|
unsigned node_based_edge_counter = 0;
|
||||||
|
unsigned original_edges_counter = 0;
|
||||||
|
|
||||||
INFO("Identifying small components");
|
std::ofstream edge_data_file(
|
||||||
|
original_edge_data_filename,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
//writes a dummy value that is updated later
|
||||||
|
edge_data_file.write(
|
||||||
|
(char*)&original_edges_counter,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
|
||||||
|
unsigned current_component = 0, current_component_size = 0;
|
||||||
//Run a BFS on the undirected graph and identify small components
|
//Run a BFS on the undirected graph and identify small components
|
||||||
std::queue<std::pair<NodeID, NodeID> > bfsQueue;
|
std::queue<std::pair<NodeID, NodeID> > bfs_queue;
|
||||||
std::vector<unsigned> componentsIndex(_nodeBasedGraph->GetNumberOfNodes(), UINT_MAX);
|
std::vector<unsigned> component_index_list(
|
||||||
std::vector<NodeID> vectorOfComponentSizes;
|
m_node_based_graph->GetNumberOfNodes(),
|
||||||
unsigned currentComponent = 0, sizeOfCurrentComponent = 0;
|
UINT_MAX
|
||||||
|
);
|
||||||
|
|
||||||
|
std::vector<NodeID> component_size_list;
|
||||||
//put unexplorered node with parent pointer into queue
|
//put unexplorered node with parent pointer into queue
|
||||||
for(NodeID node = 0, endNodes = _nodeBasedGraph->GetNumberOfNodes(); node < endNodes; ++node) {
|
for(
|
||||||
if(UINT_MAX == componentsIndex[node]) {
|
NodeID node = 0,
|
||||||
bfsQueue.push(std::make_pair(node, node));
|
last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
node < last_node;
|
||||||
|
++node
|
||||||
|
) {
|
||||||
|
if(UINT_MAX == component_index_list[node]) {
|
||||||
|
bfs_queue.push(std::make_pair(node, node));
|
||||||
//mark node as read
|
//mark node as read
|
||||||
componentsIndex[node] = currentComponent;
|
component_index_list[node] = current_component;
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
while(!bfsQueue.empty()) {
|
while(!bfs_queue.empty()) {
|
||||||
//fetch element from BFS queue
|
//fetch element from BFS queue
|
||||||
std::pair<NodeID, NodeID> currentQueueItem = bfsQueue.front();
|
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||||
bfsQueue.pop();
|
bfs_queue.pop();
|
||||||
// INFO("sizeof queue: " << bfsQueue.size() << ", sizeOfCurrentComponents: " << sizeOfCurrentComponent << ", settled nodes: " << settledNodes++ << ", max: " << endNodes);
|
// SimpleLogger().Write() << "sizeof queue: " << bfs_queue.size() <<
|
||||||
const NodeID v = currentQueueItem.first; //current node
|
// ", current_component_sizes: " << current_component_size <<
|
||||||
const NodeID u = currentQueueItem.second; //parent
|
//", settled nodes: " << settledNodes++ << ", max: " << endNodes;
|
||||||
|
const NodeID v = current_queue_item.first; //current node
|
||||||
|
const NodeID u = current_queue_item.second; //parent
|
||||||
//increment size counter of current component
|
//increment size counter of current component
|
||||||
++sizeOfCurrentComponent;
|
++current_component_size;
|
||||||
const bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
|
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
if(!isBollardNode) {
|
if(!is_barrier_node) {
|
||||||
const NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
|
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
|
||||||
//relaxieren edge outgoing edge like below where edge-expanded graph
|
//relaxieren edge outgoing edge like below where edge-expanded graph
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
for(
|
||||||
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
|
EdgeIterator e2 = m_node_based_graph->BeginEdges(v);
|
||||||
|
e2 < m_node_based_graph->EndEdges(v);
|
||||||
|
++e2
|
||||||
|
) {
|
||||||
|
NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||||
|
|
||||||
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
|
if(
|
||||||
|
to_node_of_only_restriction != UINT_MAX &&
|
||||||
|
w != to_node_of_only_restriction
|
||||||
|
) {
|
||||||
|
//We are at an only_-restriction but not at the right turn.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( u != w ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
if( u != w ) {
|
||||||
if (!CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited
|
//only add an edge if turn is not a U-turn except
|
||||||
//insert next (node, parent) only if w has not yet been explored
|
//when it is at the end of a dead-end street.
|
||||||
if(UINT_MAX == componentsIndex[w]) {
|
if (!CheckIfTurnIsRestricted(u, v, w) ) {
|
||||||
|
//only add an edge if turn is not prohibited
|
||||||
|
if(UINT_MAX == component_index_list[w]) {
|
||||||
|
//insert next (node, parent) only if w has
|
||||||
|
//not yet been explored
|
||||||
//mark node as read
|
//mark node as read
|
||||||
componentsIndex[w] = currentComponent;
|
component_index_list[w] = current_component;
|
||||||
bfsQueue.push(std::make_pair(w,v));
|
bfs_queue.push(std::make_pair(w,v));
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,176 +284,278 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//push size into vector
|
//push size into vector
|
||||||
vectorOfComponentSizes.push_back(sizeOfCurrentComponent);
|
component_size_list.push_back(current_component_size);
|
||||||
//reset counters;
|
//reset counters;
|
||||||
sizeOfCurrentComponent = 0;
|
current_component_size = 0;
|
||||||
++currentComponent;
|
++current_component;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INFO("identified: " << vectorOfComponentSizes.size() << " many components");
|
SimpleLogger().Write() <<
|
||||||
|
"identified: " << component_size_list.size() << " many components";
|
||||||
|
|
||||||
p.reinit(_nodeBasedGraph->GetNumberOfNodes());
|
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||||
//loop over all edges and generate new set of nodes.
|
//loop over all edges and generate new set of nodes.
|
||||||
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
for(
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
NodeIterator u = 0,
|
||||||
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||||
|
u < number_of_nodes;
|
||||||
|
++u
|
||||||
|
) {
|
||||||
|
for(
|
||||||
|
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
||||||
|
last_edge = m_node_based_graph->EndEdges(u);
|
||||||
|
e1 < last_edge;
|
||||||
|
++e1
|
||||||
|
) {
|
||||||
|
NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
|
||||||
if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) {
|
if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) {
|
||||||
assert(e1 != UINT_MAX);
|
BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid");
|
||||||
assert(u != UINT_MAX);
|
BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid");
|
||||||
assert(v != UINT_MAX);
|
BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid");
|
||||||
//edges that end on bollard nodes may actually be in two distinct components
|
//Note: edges that end on barrier nodes or on a turn restriction
|
||||||
InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) );
|
//may actually be in two distinct components. We choose the smallest
|
||||||
|
const unsigned size_of_component = std::min(
|
||||||
|
component_size_list[component_index_list[u]],
|
||||||
|
component_size_list[component_index_list[v]]
|
||||||
|
);
|
||||||
|
|
||||||
|
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NodeID>().swap(vectorOfComponentSizes);
|
std::vector<NodeID>().swap(component_size_list);
|
||||||
std::vector<NodeID>().swap(componentsIndex);
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == component_size_list.capacity(),
|
||||||
|
"component size vector not deallocated"
|
||||||
|
);
|
||||||
|
std::vector<NodeID>().swap(component_index_list);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == component_index_list.capacity(),
|
||||||
|
"component index vector not deallocated"
|
||||||
|
);
|
||||||
|
std::vector<OriginalEdgeData> original_edge_data_vector;
|
||||||
|
original_edge_data_vector.reserve(10000);
|
||||||
|
|
||||||
//Loop over all turns and generate new set of edges.
|
//Loop over all turns and generate new set of edges.
|
||||||
//Three nested loop look super-linear, but we are dealing with a linear number of turns only.
|
//Three nested loop look super-linear, but we are dealing with a (kind of)
|
||||||
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
|
//linear number of turns only.
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) {
|
for(
|
||||||
++nodeBasedEdgeCounter;
|
NodeIterator u = 0,
|
||||||
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
|
last_node = m_node_based_graph->GetNumberOfNodes();
|
||||||
//EdgeWeight heightPenalty = ComputeHeightPenalty(u, v);
|
u < last_node;
|
||||||
NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v);
|
++u
|
||||||
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
|
) {
|
||||||
const _NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
|
for(
|
||||||
|
EdgeIterator e1 = m_node_based_graph->BeginEdges(u),
|
||||||
if(onlyToNode != UINT_MAX && w != onlyToNode) { //We are at an only_-restriction but not at the right turn.
|
last_edge_u = m_node_based_graph->EndEdges(u);
|
||||||
++numberOfSkippedTurns;
|
e1 < last_edge_u;
|
||||||
continue;
|
++e1
|
||||||
}
|
) {
|
||||||
bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end());
|
++node_based_edge_counter;
|
||||||
if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) {
|
NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||||
|
bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||||
|
NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||||
|
for(
|
||||||
|
EdgeIterator e2 = m_node_based_graph->BeginEdges(v),
|
||||||
|
last_edge_v = m_node_based_graph->EndEdges(v);
|
||||||
|
e2 < last_edge_v;
|
||||||
|
++e2
|
||||||
|
) {
|
||||||
|
const NodeIterator w = m_node_based_graph->GetTarget(e2);
|
||||||
|
if(
|
||||||
|
to_node_of_only_restriction != UINT_MAX &&
|
||||||
|
w != to_node_of_only_restriction
|
||||||
|
) {
|
||||||
|
//We are at an only_-restriction but not at the right turn.
|
||||||
|
++skipped_turns_counter;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isBollardNode ) { //only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) {
|
||||||
if (!CheckIfTurnIsRestricted(u, v, w) || (onlyToNode != UINT_MAX && w == onlyToNode)) { //only add an edge if turn is not prohibited
|
continue;
|
||||||
const _NodeBasedDynamicGraph::EdgeData edgeData1 = _nodeBasedGraph->GetEdgeData(e1);
|
}
|
||||||
const _NodeBasedDynamicGraph::EdgeData edgeData2 = _nodeBasedGraph->GetEdgeData(e2);
|
|
||||||
assert(edgeData1.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
|
|
||||||
assert(edgeData2.edgeBasedNodeID < _nodeBasedGraph->GetNumberOfEdges());
|
|
||||||
|
|
||||||
if(!edgeData1.forward || !edgeData2.forward) {
|
if( !is_barrier_node ) {
|
||||||
|
//only add an edge if turn is not a U-turn except when it is
|
||||||
|
//at the end of a dead-end street
|
||||||
|
if (
|
||||||
|
!CheckIfTurnIsRestricted(u, v, w) ||
|
||||||
|
(to_node_of_only_restriction != UINT_MAX && w == to_node_of_only_restriction)
|
||||||
|
) { //only add an edge if turn is not prohibited
|
||||||
|
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||||
|
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||||
|
assert(edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
|
||||||
|
assert(edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges());
|
||||||
|
|
||||||
|
if(!edge_data1.forward || !edge_data2.forward) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned distance = edgeData1.distance;
|
unsigned distance = edge_data1.distance;
|
||||||
if(_trafficLights.find(v) != _trafficLights.end()) {
|
if(m_traffic_lights.find(v) != m_traffic_lights.end()) {
|
||||||
distance += speedProfile.trafficSignalPenalty;
|
distance += speed_profile.trafficSignalPenalty;
|
||||||
}
|
}
|
||||||
|
const unsigned penalty =
|
||||||
|
GetTurnPenalty(u, v, w, lua_state);
|
||||||
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
||||||
if(turnInstruction == TurnInstructions.UTurn)
|
if(turnInstruction == TurnInstructions.UTurn){
|
||||||
distance += speedProfile.uTurnPenalty;
|
distance += speed_profile.uTurnPenalty;
|
||||||
// if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) {
|
|
||||||
// distance += TurnInstructions.AccessRestrictionPenalty;
|
|
||||||
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
//distance += heightPenalty;
|
|
||||||
//distance += ComputeTurnPenalty(u, v, w);
|
|
||||||
assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID);
|
|
||||||
if(originalEdgeData.size() == originalEdgeData.capacity()-3) {
|
|
||||||
originalEdgeData.reserve(originalEdgeData.size()*1.2);
|
|
||||||
}
|
}
|
||||||
OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction);
|
distance += penalty;
|
||||||
EdgeBasedEdge newEdge(edgeData1.edgeBasedNodeID, edgeData2.edgeBasedNodeID, edgeBasedEdges.size(), distance, true, false );
|
|
||||||
originalEdgeData.push_back(oed);
|
assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||||
if(originalEdgeData.size() > 100000) {
|
original_edge_data_vector.push_back(
|
||||||
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
|
OriginalEdgeData(
|
||||||
originalEdgeData.clear();
|
v,
|
||||||
|
edge_data2.nameID,
|
||||||
|
turnInstruction
|
||||||
|
)
|
||||||
|
);
|
||||||
|
++original_edges_counter;
|
||||||
|
|
||||||
|
if(original_edge_data_vector.size() > 100000) {
|
||||||
|
edge_data_file.write(
|
||||||
|
(char*)&(original_edge_data_vector[0]),
|
||||||
|
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
|
||||||
|
);
|
||||||
|
original_edge_data_vector.clear();
|
||||||
}
|
}
|
||||||
++numberOfOriginalEdges;
|
|
||||||
++nodeBasedEdgeCounter;
|
m_edge_based_edge_list.push_back(
|
||||||
edgeBasedEdges.push_back(newEdge);
|
EdgeBasedEdge(
|
||||||
|
edge_data1.edgeBasedNodeID,
|
||||||
|
edge_data2.edgeBasedNodeID,
|
||||||
|
m_edge_based_edge_list.size(),
|
||||||
|
distance,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
++numberOfSkippedTurns;
|
++skipped_turns_counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.printIncrement();
|
p.printIncrement();
|
||||||
}
|
}
|
||||||
numberOfOriginalEdges += originalEdgeData.size();
|
edge_data_file.write(
|
||||||
originalEdgeDataOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
|
(char*)&(original_edge_data_vector[0]),
|
||||||
originalEdgeDataOutFile.seekp(std::ios::beg);
|
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
|
||||||
originalEdgeDataOutFile.write((char*)&numberOfOriginalEdges, sizeof(unsigned));
|
);
|
||||||
originalEdgeDataOutFile.close();
|
edge_data_file.seekp(std::ios::beg);
|
||||||
|
edge_data_file.write(
|
||||||
|
(char*)&original_edges_counter,
|
||||||
|
sizeof(unsigned)
|
||||||
|
);
|
||||||
|
edge_data_file.close();
|
||||||
|
|
||||||
// INFO("Sorting edge-based Nodes");
|
SimpleLogger().Write() <<
|
||||||
// std::sort(edgeBasedNodes.begin(), edgeBasedNodes.end());
|
"Generated " << m_edge_based_node_list.size() << " edge based nodes";
|
||||||
// INFO("Removing duplicate nodes (if any)");
|
SimpleLogger().Write() <<
|
||||||
// edgeBasedNodes.erase( std::unique(edgeBasedNodes.begin(), edgeBasedNodes.end()), edgeBasedNodes.end() );
|
"Node-based graph contains " << node_based_edge_counter << " edges";
|
||||||
// INFO("Applying vector self-swap trick to free up memory");
|
SimpleLogger().Write() <<
|
||||||
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
|
"Edge-expanded graph ...";
|
||||||
// std::vector<EdgeBasedNode>(edgeBasedNodes).swap(edgeBasedNodes);
|
SimpleLogger().Write() <<
|
||||||
// INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity());
|
" contains " << m_edge_based_edge_list.size() << " edges";
|
||||||
INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges");
|
SimpleLogger().Write() <<
|
||||||
// INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter));
|
" skips " << skipped_turns_counter << " turns, "
|
||||||
INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions.");
|
"defined by " << m_turn_restrictions_count << " restrictions";
|
||||||
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
|
int EdgeBasedGraphFactory::GetTurnPenalty(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w,
|
||||||
|
lua_State *lua_state
|
||||||
|
) const {
|
||||||
|
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
|
||||||
|
m_node_info_list[u],
|
||||||
|
m_node_info_list[v],
|
||||||
|
m_node_info_list[w]
|
||||||
|
);
|
||||||
|
|
||||||
|
if( speed_profile.has_turn_penalty_function ) {
|
||||||
|
try {
|
||||||
|
//call lua profile to compute turn penalty
|
||||||
|
return luabind::call_function<int>(
|
||||||
|
lua_state,
|
||||||
|
"turn_function",
|
||||||
|
180.-angle
|
||||||
|
);
|
||||||
|
} catch (const luabind::error &er) {
|
||||||
|
SimpleLogger().Write(logWARNING) << er.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const {
|
||||||
if(u == w) {
|
if(u == w) {
|
||||||
return TurnInstructions.UTurn;
|
return TurnInstructions.UTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
_NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
|
EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
|
||||||
_NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
|
EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
|
||||||
|
|
||||||
_NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1);
|
EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||||
_NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2);
|
EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||||
|
|
||||||
|
if(!data1.contraFlow && data2.contraFlow) {
|
||||||
|
return TurnInstructions.EnterAgainstAllowedDirection;
|
||||||
|
}
|
||||||
|
if(data1.contraFlow && !data2.contraFlow) {
|
||||||
|
return TurnInstructions.LeaveAgainstAllowedDirection;
|
||||||
|
}
|
||||||
|
|
||||||
//roundabouts need to be handled explicitely
|
//roundabouts need to be handled explicitely
|
||||||
if(data1.roundabout && data2.roundabout) {
|
if(data1.roundabout && data2.roundabout) {
|
||||||
//Is a turn possible? If yes, we stay on the roundabout!
|
//Is a turn possible? If yes, we stay on the roundabout!
|
||||||
if( 1 == (_nodeBasedGraph->EndEdges(v) - _nodeBasedGraph->BeginEdges(v)) ) {
|
if( 1 == m_node_based_graph->GetOutDegree(v) ) {
|
||||||
//No turn possible.
|
//No turn possible.
|
||||||
return TurnInstructions.NoTurn;
|
return TurnInstructions.NoTurn;
|
||||||
} else {
|
|
||||||
return TurnInstructions.StayOnRoundAbout;
|
|
||||||
}
|
}
|
||||||
|
return TurnInstructions.StayOnRoundAbout;
|
||||||
}
|
}
|
||||||
//Does turn start or end on roundabout?
|
//Does turn start or end on roundabout?
|
||||||
if(data1.roundabout || data2.roundabout) {
|
if(data1.roundabout || data2.roundabout) {
|
||||||
//We are entering the roundabout
|
//We are entering the roundabout
|
||||||
if( (!data1.roundabout) && data2.roundabout)
|
if( (!data1.roundabout) && data2.roundabout) {
|
||||||
return TurnInstructions.EnterRoundAbout;
|
return TurnInstructions.EnterRoundAbout;
|
||||||
|
}
|
||||||
//We are leaving the roundabout
|
//We are leaving the roundabout
|
||||||
else if(data1.roundabout && (!data2.roundabout) )
|
if(data1.roundabout && (!data2.roundabout) ) {
|
||||||
return TurnInstructions.LeaveRoundAbout;
|
return TurnInstructions.LeaveRoundAbout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//If street names stay the same and if we are certain that it is not a roundabout, we skip it.
|
//If street names stay the same and if we are certain that it is not a
|
||||||
if( (data1.nameID == data2.nameID) && (0 != data1.nameID))
|
//a segment of a roundabout, we skip it.
|
||||||
return TurnInstructions.NoTurn;
|
if( data1.nameID == data2.nameID ) {
|
||||||
if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) )
|
//TODO: Here we should also do a small graph exploration to check for
|
||||||
return TurnInstructions.NoTurn;
|
// more complex situations
|
||||||
|
if( 0 != data1.nameID ) {
|
||||||
|
return TurnInstructions.NoTurn;
|
||||||
|
} else if (m_node_based_graph->GetOutDegree(v) <= 2) {
|
||||||
|
return TurnInstructions.NoTurn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double angle = GetAngleBetweenThreeFixedPointCoordinates (
|
||||||
|
m_node_info_list[u],
|
||||||
|
m_node_info_list[v],
|
||||||
|
m_node_info_list[w]
|
||||||
|
);
|
||||||
|
|
||||||
double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
|
|
||||||
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
||||||
return _nodeBasedGraph->GetNumberOfEdges();
|
return m_node_based_graph->GetNumberOfEdges();
|
||||||
}
|
|
||||||
|
|
||||||
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
|
||||||
template<class CoordinateT>
|
|
||||||
double EdgeBasedGraphFactory::GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const {
|
|
||||||
const int v1x = A.lon - C.lon;
|
|
||||||
const int v1y = A.lat - C.lat;
|
|
||||||
const int v2x = B.lon - C.lon;
|
|
||||||
const int v2y = B.lat - C.lat;
|
|
||||||
|
|
||||||
double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI;
|
|
||||||
while(angle < 0)
|
|
||||||
angle += 360;
|
|
||||||
return angle;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,25 +18,11 @@
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
// This class constructs the edge-expanded routing graph
|
||||||
* This class constructs the edge base representation of a graph from a given node based edge list
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef EDGEBASEDGRAPHFACTORY_H_
|
#ifndef EDGEBASEDGRAPHFACTORY_H_
|
||||||
#define EDGEBASEDGRAPHFACTORY_H_
|
#define EDGEBASEDGRAPHFACTORY_H_
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
#include <stxxl.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
@@ -46,44 +32,57 @@
|
|||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/BaseConfiguration.h"
|
#include "../Util/LuaUtil.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
class EdgeBasedGraphFactory {
|
#include <boost/foreach.hpp>
|
||||||
private:
|
#include <boost/make_shared.hpp>
|
||||||
struct _NodeBasedEdgeData {
|
#include <boost/noncopyable.hpp>
|
||||||
int distance;
|
#include <boost/shared_ptr.hpp>
|
||||||
unsigned edgeBasedNodeID;
|
#include <boost/unordered_map.hpp>
|
||||||
unsigned nameID:31;
|
#include <boost/unordered_set.hpp>
|
||||||
bool shortcut:1;
|
|
||||||
bool forward:1;
|
|
||||||
bool backward:1;
|
|
||||||
bool roundabout:1;
|
|
||||||
bool ignoreInGrid:1;
|
|
||||||
short type;
|
|
||||||
bool isAccessRestricted;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _EdgeBasedEdgeData {
|
#include <algorithm>
|
||||||
int distance;
|
#include <fstream>
|
||||||
unsigned via;
|
#include <queue>
|
||||||
unsigned nameID;
|
#include <vector>
|
||||||
bool forward;
|
|
||||||
bool backward;
|
|
||||||
TurnInstruction turnInstruction;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph;
|
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||||
typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge;
|
|
||||||
std::vector<NodeInfo> inputNodeInfoList;
|
|
||||||
unsigned numberOfTurnRestrictions;
|
|
||||||
public:
|
public:
|
||||||
struct EdgeBasedNode {
|
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 {
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
return other.id < id;
|
return other.id < id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
bool operator==(const EdgeBasedNode & other) const {
|
||||||
return id == other.id;
|
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;
|
NodeID id;
|
||||||
int lat1;
|
int lat1;
|
||||||
int lat2;
|
int lat2;
|
||||||
@@ -95,51 +94,110 @@ public:
|
|||||||
bool ignoreInGrid:1;
|
bool ignoreInGrid:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SpeedProfileProperties{
|
struct SpeedProfileProperties{
|
||||||
SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {}
|
SpeedProfileProperties() :
|
||||||
|
trafficSignalPenalty(0),
|
||||||
|
uTurnPenalty(0),
|
||||||
|
has_turn_penalty_function(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
int trafficSignalPenalty;
|
int trafficSignalPenalty;
|
||||||
int uTurnPenalty;
|
int uTurnPenalty;
|
||||||
} speedProfile;
|
bool has_turn_penalty_function;
|
||||||
private:
|
} speed_profile;
|
||||||
boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph;
|
|
||||||
boost::unordered_map<NodeID, bool> _barrierNodes;
|
|
||||||
boost::unordered_map<NodeID, bool> _trafficLights;
|
|
||||||
|
|
||||||
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
explicit EdgeBasedGraphFactory(
|
||||||
typedef std::pair<NodeID, bool> RestrictionTarget;
|
int number_of_nodes,
|
||||||
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
std::vector<ImportEdge> & input_edge_list,
|
||||||
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
std::vector<NodeID> & barrier_node_list,
|
||||||
std::vector<EmanatingRestrictionsVector> _restrictionBucketVector;
|
std::vector<NodeID> & traffic_light_node_list,
|
||||||
RestrictionMap _restrictionMap;
|
std::vector<TurnRestriction> & input_restrictions_list,
|
||||||
|
std::vector<NodeInfo> & m_node_info_list,
|
||||||
|
SpeedProfileProperties speed_profile
|
||||||
|
);
|
||||||
|
|
||||||
|
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
|
||||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
|
|
||||||
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
|
|
||||||
std::vector<OriginalEdgeData> originalEdgeData;
|
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
|
||||||
void InsertEdgeBasedNode(
|
|
||||||
_NodeBasedDynamicGraph::EdgeIterator e1,
|
|
||||||
_NodeBasedDynamicGraph::NodeIterator u,
|
|
||||||
_NodeBasedDynamicGraph::NodeIterator v,
|
|
||||||
bool belongsToTinyComponent);
|
|
||||||
template<class CoordinateT>
|
|
||||||
double GetAngleBetweenTwoEdges(const CoordinateT& A, const CoordinateT& C, const CoordinateT& B) const;
|
|
||||||
// SRTMLookup srtmLookup;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
template< class InputEdgeT >
|
|
||||||
explicit EdgeBasedGraphFactory(int nodes, std::vector<InputEdgeT> & inputEdges, std::vector<NodeID> & _bollardNodes, std::vector<NodeID> & trafficLights, std::vector<_Restriction> & inputRestrictions, std::vector<NodeInfo> & nI, SpeedProfileProperties speedProfile);
|
|
||||||
|
|
||||||
void Run(const char * originalEdgeDataFilename);
|
|
||||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||||
void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes);
|
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||||
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
|
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
|
||||||
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
|
TurnInstruction AnalyzeTurn(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const;
|
||||||
|
int GetTurnPenalty(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w,
|
||||||
|
lua_State *myLuaState
|
||||||
|
) const;
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const;
|
unsigned GetNumberOfNodes() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct NodeBasedEdgeData {
|
||||||
|
int distance;
|
||||||
|
unsigned edgeBasedNodeID;
|
||||||
|
unsigned nameID;
|
||||||
|
short type;
|
||||||
|
bool isAccessRestricted:1;
|
||||||
|
bool shortcut:1;
|
||||||
|
bool forward:1;
|
||||||
|
bool backward:1;
|
||||||
|
bool roundabout:1;
|
||||||
|
bool ignoreInGrid:1;
|
||||||
|
bool contraFlow:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _EdgeBasedEdgeData {
|
||||||
|
int distance;
|
||||||
|
unsigned via;
|
||||||
|
unsigned nameID;
|
||||||
|
bool forward;
|
||||||
|
bool backward;
|
||||||
|
TurnInstruction turnInstruction;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned m_turn_restrictions_count;
|
||||||
|
|
||||||
|
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
|
||||||
|
typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge;
|
||||||
|
typedef NodeBasedDynamicGraph::NodeIterator NodeIterator;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator;
|
||||||
|
typedef NodeBasedDynamicGraph::EdgeData EdgeData;
|
||||||
|
typedef std::pair<NodeID, NodeID> RestrictionSource;
|
||||||
|
typedef std::pair<NodeID, bool> RestrictionTarget;
|
||||||
|
typedef std::vector<RestrictionTarget> EmanatingRestrictionsVector;
|
||||||
|
typedef boost::unordered_map<RestrictionSource, unsigned > RestrictionMap;
|
||||||
|
|
||||||
|
std::vector<NodeInfo> m_node_info_list;
|
||||||
|
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||||
|
std::vector<EdgeBasedNode> m_edge_based_node_list;
|
||||||
|
DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||||
|
|
||||||
|
boost::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||||
|
boost::unordered_set<NodeID> m_barrier_nodes;
|
||||||
|
boost::unordered_set<NodeID> m_traffic_lights;
|
||||||
|
|
||||||
|
RestrictionMap m_restriction_map;
|
||||||
|
|
||||||
|
|
||||||
|
NodeID CheckForEmanatingIsOnlyTurn(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v
|
||||||
|
) const;
|
||||||
|
|
||||||
|
bool CheckIfTurnIsRestricted(
|
||||||
|
const NodeID u,
|
||||||
|
const NodeID v,
|
||||||
|
const NodeID w
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void InsertEdgeBasedNode(
|
||||||
|
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||||
|
NodeBasedDynamicGraph::NodeIterator u,
|
||||||
|
NodeBasedDynamicGraph::NodeIterator v,
|
||||||
|
bool belongsToTinyComponent);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||||
|
|||||||
@@ -18,16 +18,10 @@
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
|
|
||||||
TemporaryStorage::TemporaryStorage() {
|
TemporaryStorage::TemporaryStorage() {
|
||||||
try {
|
tempDirectory = boost::filesystem::temp_directory_path();
|
||||||
tempDirectory = boost::filesystem::temp_directory_path();
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
ERR("could not retrieve location of temporary path: " << e.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
TemporaryStorage & TemporaryStorage::GetInstance(){
|
||||||
@@ -41,12 +35,8 @@ TemporaryStorage::~TemporaryStorage() {
|
|||||||
|
|
||||||
void TemporaryStorage::removeAll() {
|
void TemporaryStorage::removeAll() {
|
||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
|
||||||
for(unsigned slotID = 0; slotID < vectorOfStreamDatas.size(); ++slotID)
|
deallocateSlot(slot_id);
|
||||||
deallocateSlot(slotID);
|
|
||||||
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
|
||||||
ERR("could not retrieve location of temporary path: " << e.what());
|
|
||||||
}
|
}
|
||||||
vectorOfStreamDatas.clear();
|
vectorOfStreamDatas.clear();
|
||||||
}
|
}
|
||||||
@@ -55,7 +45,7 @@ int TemporaryStorage::allocateSlot() {
|
|||||||
boost::mutex::scoped_lock lock(mutex);
|
boost::mutex::scoped_lock lock(mutex);
|
||||||
try {
|
try {
|
||||||
vectorOfStreamDatas.push_back(StreamData());
|
vectorOfStreamDatas.push_back(StreamData());
|
||||||
//INFO("created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile);
|
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
}
|
}
|
||||||
@@ -66,13 +56,13 @@ void TemporaryStorage::deallocateSlot(int slotID) {
|
|||||||
try {
|
try {
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
StreamData & data = vectorOfStreamDatas[slotID];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(data.streamToTemporaryFile->is_open())
|
if(data.streamToTemporaryFile->is_open()) {
|
||||||
data.streamToTemporaryFile->close();
|
data.streamToTemporaryFile->close();
|
||||||
|
}
|
||||||
|
|
||||||
//INFO("deallocating slot " << slotID << " and its file: " << data.pathToTemporaryFile);
|
|
||||||
boost::filesystem::remove(data.pathToTemporaryFile);
|
boost::filesystem::remove(data.pathToTemporaryFile);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
@@ -83,8 +73,10 @@ void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize s
|
|||||||
try {
|
try {
|
||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
StreamData & data = vectorOfStreamDatas[slotID];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
if(!data.writeMode)
|
BOOST_ASSERT_MSG(
|
||||||
ERR("Writing after first read is not allowed");
|
data.writeMode,
|
||||||
|
"Writing after first read is not allowed"
|
||||||
|
);
|
||||||
data.streamToTemporaryFile->write(pointer, size);
|
data.streamToTemporaryFile->write(pointer, size);
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
@@ -123,13 +115,11 @@ boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
|
|||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
}
|
}
|
||||||
// INFO("telling position: " << position);
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
||||||
removeAll();
|
removeAll();
|
||||||
// ERR("I/O Error occured: " << e.what());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
|
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
|
||||||
@@ -137,7 +127,6 @@ void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type pos
|
|||||||
StreamData & data = vectorOfStreamDatas[slotID];
|
StreamData & data = vectorOfStreamDatas[slotID];
|
||||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||||
data.streamToTemporaryFile->seekg(position);
|
data.streamToTemporaryFile->seekg(position);
|
||||||
// INFO("seeking to position: " << position);
|
|
||||||
} catch(boost::filesystem::filesystem_error & e) {
|
} catch(boost::filesystem::filesystem_error & e) {
|
||||||
abort(e);
|
abort(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,17 +24,21 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
//This is one big workaround for latest boost renaming woes.
|
//This is one big workaround for latest boost renaming woes.
|
||||||
|
|
||||||
#ifndef BOOST_FILESYSTEM_VERSION
|
#if BOOST_FILESYSTEM_VERSION < 3
|
||||||
#warning Boost Installation with Filesystem3 (>=1.44) is required, activating workaround
|
#warning Boost Installation with Filesystem3 missing, activating workaround
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace filesystem {
|
namespace filesystem {
|
||||||
@@ -54,8 +58,9 @@ inline path unique_path(const path&) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOOST_FILESYSTEM_VERSION
|
||||||
#define BOOST_FILESYSTEM_VERSION 3
|
#define BOOST_FILESYSTEM_VERSION 3
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* This class implements a singleton file storage for temporary data.
|
* This class implements a singleton file storage for temporary data.
|
||||||
* temporary slots can be accessed by other objects through an int
|
* temporary slots can be accessed by other objects through an int
|
||||||
@@ -89,8 +94,6 @@ private:
|
|||||||
}
|
}
|
||||||
void abort(boost::filesystem::filesystem_error& e);
|
void abort(boost::filesystem::filesystem_error& e);
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
struct StreamData {
|
struct StreamData {
|
||||||
bool writeMode;
|
bool writeMode;
|
||||||
boost::filesystem::path pathToTemporaryFile;
|
boost::filesystem::path pathToTemporaryFile;
|
||||||
@@ -102,8 +105,9 @@ private:
|
|||||||
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
||||||
readWriteMutex(new boost::mutex)
|
readWriteMutex(new boost::mutex)
|
||||||
{
|
{
|
||||||
if(streamToTemporaryFile->fail())
|
if(streamToTemporaryFile->fail()) {
|
||||||
ERR("Aborting, because temporary file at " << pathToTemporaryFile << " could not be created");
|
throw OSRMException("temporary file could not be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//vector of file streams that is used to store temporary data
|
//vector of file streams that is used to store temporary data
|
||||||
|
|||||||
+17
-12
@@ -23,13 +23,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
//Not compatible with non contiguous node ids
|
//Not compatible with non contiguous node ids
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template< typename NodeID, typename Key >
|
||||||
class ArrayStorage {
|
class ArrayStorage {
|
||||||
public:
|
public:
|
||||||
@@ -75,10 +77,13 @@ template< typename NodeID, typename Key >
|
|||||||
class UnorderedMapStorage {
|
class UnorderedMapStorage {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UnorderedMapStorage( size_t ) { }
|
UnorderedMapStorage( size_t ) {
|
||||||
|
//hash table gets 1000 Buckets
|
||||||
|
nodes.rehash(1000);
|
||||||
|
}
|
||||||
|
|
||||||
Key &operator[]( NodeID node ) {
|
Key &operator[]( const NodeID node ) {
|
||||||
return nodes[node];
|
return nodes[node];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
@@ -142,13 +147,13 @@ public:
|
|||||||
return insertedNodes[index].weight;
|
return insertedNodes[index].weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasRemoved( NodeID node ) {
|
bool WasRemoved( const NodeID node ) {
|
||||||
assert( WasInserted( node ) );
|
assert( WasInserted( node ) );
|
||||||
const Key index = nodeIndex[node];
|
const Key index = nodeIndex[node];
|
||||||
return insertedNodes[index].key == 0;
|
return insertedNodes[index].key == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WasInserted( NodeID node ) {
|
bool WasInserted( const NodeID node ) {
|
||||||
const Key index = nodeIndex[node];
|
const Key index = nodeIndex[node];
|
||||||
if ( index >= static_cast<Key> (insertedNodes.size()) )
|
if ( index >= static_cast<Key> (insertedNodes.size()) )
|
||||||
return false;
|
return false;
|
||||||
@@ -181,8 +186,8 @@ public:
|
|||||||
|
|
||||||
void DecreaseKey( NodeID node, Weight weight ) {
|
void DecreaseKey( NodeID node, Weight weight ) {
|
||||||
assert( UINT_MAX != node );
|
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 );
|
assert ( key >= 0 );
|
||||||
|
|
||||||
insertedNodes[index].weight = weight;
|
insertedNodes[index].weight = weight;
|
||||||
|
|||||||
+76
-19
@@ -18,17 +18,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef COORDINATE_H_
|
#ifndef FIXED_POINT_COORDINATE_H_
|
||||||
#define COORDINATE_H_
|
#define FIXED_POINT_COORDINATE_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/MercatorUtil.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
struct _Coordinate {
|
static const double COORDINATE_PRECISION = 1000000.;
|
||||||
|
|
||||||
|
struct FixedPointCoordinate {
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
_Coordinate () : lat(INT_MIN), lon(INT_MIN) {}
|
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {}
|
||||||
_Coordinate (int t, int n) : lat(t) , lon(n) {}
|
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(lon) {}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
lat = INT_MIN;
|
lat = INT_MIN;
|
||||||
lon = INT_MIN;
|
lon = INT_MIN;
|
||||||
@@ -37,17 +46,22 @@ struct _Coordinate {
|
|||||||
return (INT_MIN != lat) && (INT_MIN != lon);
|
return (INT_MIN != lat) && (INT_MIN != lon);
|
||||||
}
|
}
|
||||||
inline bool isValid() const {
|
inline bool isValid() const {
|
||||||
if(lat > 90*100000 || lat < -90*100000 || lon > 180*100000 || lon <-180*100000) {
|
if(
|
||||||
|
lat > 90*COORDINATE_PRECISION ||
|
||||||
|
lat < -90*COORDINATE_PRECISION ||
|
||||||
|
lon > 180*COORDINATE_PRECISION ||
|
||||||
|
lon < -180*COORDINATE_PRECISION
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool operator==(const _Coordinate & other) const {
|
bool operator==(const FixedPointCoordinate & other) const {
|
||||||
return lat == other.lat && lon == other.lon;
|
return lat == other.lat && lon == other.lon;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream & out, const _Coordinate & c){
|
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
|
||||||
out << "(" << c.lat << "," << c.lon << ")";
|
out << "(" << c.lat << "," << c.lon << ")";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -58,10 +72,10 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
|
|||||||
assert(lat2 != INT_MIN);
|
assert(lat2 != INT_MIN);
|
||||||
assert(lon2 != INT_MIN);
|
assert(lon2 != INT_MIN);
|
||||||
double RAD = 0.017453292519943295769236907684886;
|
double RAD = 0.017453292519943295769236907684886;
|
||||||
double lt1 = lat1/100000.;
|
double lt1 = lat1/COORDINATE_PRECISION;
|
||||||
double ln1 = lon1/100000.;
|
double ln1 = lon1/COORDINATE_PRECISION;
|
||||||
double lt2 = lat2/100000.;
|
double lt2 = lat2/COORDINATE_PRECISION;
|
||||||
double ln2 = lon2/100000.;
|
double ln2 = lon2/COORDINATE_PRECISION;
|
||||||
double dlat1=lt1*(RAD);
|
double dlat1=lt1*(RAD);
|
||||||
|
|
||||||
double dlong1=ln1*(RAD);
|
double dlong1=ln1*(RAD);
|
||||||
@@ -80,20 +94,20 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
|
|||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateDistance(const _Coordinate &c1, const _Coordinate &c2) {
|
inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||||
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordinate &c2) {
|
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||||
assert(c1.lat != INT_MIN);
|
assert(c1.lat != INT_MIN);
|
||||||
assert(c1.lon != INT_MIN);
|
assert(c1.lon != INT_MIN);
|
||||||
assert(c2.lat != INT_MIN);
|
assert(c2.lat != INT_MIN);
|
||||||
assert(c2.lon != INT_MIN);
|
assert(c2.lon != INT_MIN);
|
||||||
const double RAD = 0.017453292519943295769236907684886;
|
const double RAD = 0.017453292519943295769236907684886;
|
||||||
const double lat1 = (c1.lat/100000.)*RAD;
|
const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD;
|
||||||
const double lon1 = (c1.lon/100000.)*RAD;
|
const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD;
|
||||||
const double lat2 = (c2.lat/100000.)*RAD;
|
const double lat2 = (c2.lat/COORDINATE_PRECISION)*RAD;
|
||||||
const double lon2 = (c2.lon/100000.)*RAD;
|
const double lon2 = (c2.lon/COORDINATE_PRECISION)*RAD;
|
||||||
|
|
||||||
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
const double x = (lon2-lon1) * cos((lat1+lat2)/2.);
|
||||||
const double y = (lat2-lat1);
|
const double y = (lat2-lat1);
|
||||||
@@ -102,5 +116,48 @@ inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordina
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void convertInternalLatLonToString(const int value, std::string & output) {
|
||||||
|
char buffer[100];
|
||||||
|
buffer[10] = 0; // Nullterminierung
|
||||||
|
char* string = printInt< 10, 6 >( buffer, value );
|
||||||
|
output = string;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* COORDINATE_H_ */
|
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||||
|
std::string tmp;
|
||||||
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
|
output = tmp;
|
||||||
|
output += ",";
|
||||||
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
|
output += tmp;
|
||||||
|
output += " ";
|
||||||
|
}
|
||||||
|
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||||
|
std::string tmp;
|
||||||
|
convertInternalLatLonToString(coord.lat, tmp);
|
||||||
|
output = tmp;
|
||||||
|
output += ",";
|
||||||
|
convertInternalLatLonToString(coord.lon, tmp);
|
||||||
|
output += tmp;
|
||||||
|
output += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||||
|
template<class CoordinateT>
|
||||||
|
static inline double GetAngleBetweenThreeFixedPointCoordinates (
|
||||||
|
const CoordinateT & A,
|
||||||
|
const CoordinateT & C,
|
||||||
|
const CoordinateT & B
|
||||||
|
) {
|
||||||
|
const double v1x = (A.lon - C.lon)/COORDINATE_PRECISION;
|
||||||
|
const double v1y = lat2y(A.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
|
||||||
|
const double v2x = (B.lon - C.lon)/COORDINATE_PRECISION;
|
||||||
|
const double v2y = lat2y(B.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
|
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI;
|
||||||
|
while(angle < 0)
|
||||||
|
angle += 360;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#define DEALLOCATINGVECTOR_H_
|
#define DEALLOCATINGVECTOR_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if __cplusplus > 199711L
|
#if __cplusplus > 199711L
|
||||||
@@ -32,7 +31,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT), bool DeallocateC = false>
|
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT), bool DeallocateC = false>
|
||||||
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
|
class DeallocatingVectorIterator : public std::iterator<std::random_access_iterator_tag, ElementT> {
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -42,12 +41,12 @@ protected:
|
|||||||
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 size_t idx, const std::vector<ElementT *> & input_list) : mData(ptr), mIndex(idx), mBucketList(input_list) {}
|
//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 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();
|
setPointerForIndex();
|
||||||
}
|
}
|
||||||
ElementT * mData;
|
ElementT * mData;
|
||||||
size_t mIndex;
|
std::size_t mIndex;
|
||||||
std::vector<ElementT *> & mBucketList;
|
std::vector<ElementT *> & mBucketList;
|
||||||
|
|
||||||
inline void setPointerForIndex() {
|
inline void setPointerForIndex() {
|
||||||
@@ -55,8 +54,8 @@ protected:
|
|||||||
mData = DEALLOCATION_VECTOR_NULL_PTR;
|
mData = DEALLOCATION_VECTOR_NULL_PTR;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t _bucket = mIndex/bucketSizeC;
|
std::size_t _bucket = mIndex/bucketSizeC;
|
||||||
size_t _index = mIndex%bucketSizeC;
|
std::size_t _index = mIndex%bucketSizeC;
|
||||||
mData = &(mBucketList[_bucket][_index]);
|
mData = &(mBucketList[_bucket][_index]);
|
||||||
|
|
||||||
if(DeallocateC) {
|
if(DeallocateC) {
|
||||||
@@ -104,8 +103,8 @@ public:
|
|||||||
template<typename T2>
|
template<typename T2>
|
||||||
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
DeallocatingVectorIterator(const DeallocatingVectorIterator<T2> & r) : mState(r.mState) {}
|
||||||
|
|
||||||
DeallocatingVectorIterator(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(size_t idx, const 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>
|
||||||
@@ -185,10 +184,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ElementT, size_t bucketSizeC = 10485760/sizeof(ElementT) >
|
template<typename ElementT, std::size_t bucketSizeC = 8388608/sizeof(ElementT) >
|
||||||
class DeallocatingVector {
|
class DeallocatingVector {
|
||||||
private:
|
private:
|
||||||
size_t mCurrentSize;
|
std::size_t mCurrentSize;
|
||||||
std::vector<ElementT *> mBucketList;
|
std::vector<ElementT *> mBucketList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -227,21 +226,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void push_back(const ElementT & element) {
|
inline void push_back(const ElementT & element) {
|
||||||
size_t _capacity = capacity();
|
std::size_t _capacity = capacity();
|
||||||
if(mCurrentSize == _capacity) {
|
if(mCurrentSize == _capacity) {
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
mBucketList.push_back(new ElementT[bucketSizeC]);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t _index = size()%bucketSizeC;
|
std::size_t _index = size()%bucketSizeC;
|
||||||
mBucketList.back()[_index] = element;
|
mBucketList.back()[_index] = element;
|
||||||
++mCurrentSize;
|
++mCurrentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reserve(const size_t) const {
|
inline void reserve(const std::size_t) const {
|
||||||
//don't do anything
|
//don't do anything
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void resize(const size_t new_size) {
|
inline void resize(const std::size_t new_size) {
|
||||||
if(new_size > mCurrentSize) {
|
if(new_size > mCurrentSize) {
|
||||||
while(capacity() < new_size) {
|
while(capacity() < new_size) {
|
||||||
mBucketList.push_back(new ElementT[bucketSizeC]);
|
mBucketList.push_back(new ElementT[bucketSizeC]);
|
||||||
@@ -249,7 +248,7 @@ public:
|
|||||||
mCurrentSize = new_size;
|
mCurrentSize = new_size;
|
||||||
}
|
}
|
||||||
if(new_size < mCurrentSize) {
|
if(new_size < mCurrentSize) {
|
||||||
size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
|
std::size_t number_of_necessary_buckets = 1+(new_size / bucketSizeC);
|
||||||
|
|
||||||
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
|
for(unsigned i = number_of_necessary_buckets; i < mBucketList.size(); ++i) {
|
||||||
delete[] mBucketList[i];
|
delete[] mBucketList[i];
|
||||||
@@ -259,16 +258,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t size() const {
|
inline std::size_t size() const {
|
||||||
return mCurrentSize;
|
return mCurrentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t capacity() const {
|
inline std::size_t capacity() const {
|
||||||
return mBucketList.size() * bucketSizeC;
|
return mBucketList.size() * bucketSizeC;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline iterator begin() {
|
inline iterator begin() {
|
||||||
return iterator(static_cast<size_t>(0), mBucketList);
|
return iterator(static_cast<std::size_t>(0), mBucketList);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline iterator end() {
|
inline iterator end() {
|
||||||
@@ -276,7 +275,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline deallocation_iterator dbegin() {
|
inline deallocation_iterator dbegin() {
|
||||||
return deallocation_iterator(static_cast<size_t>(0), mBucketList);
|
return deallocation_iterator(static_cast<std::size_t>(0), mBucketList);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline deallocation_iterator dend() {
|
inline deallocation_iterator dend() {
|
||||||
@@ -284,24 +283,36 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline const_iterator begin() const {
|
inline const_iterator begin() const {
|
||||||
return const_iterator(static_cast<size_t>(0), mBucketList);
|
return const_iterator(static_cast<std::size_t>(0), mBucketList);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const_iterator end() const {
|
inline const_iterator end() const {
|
||||||
return const_iterator(size(), mBucketList);
|
return const_iterator(size(), mBucketList);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ElementT & operator[](const size_t index) {
|
inline ElementT & operator[](const std::size_t index) {
|
||||||
size_t _bucket = index / bucketSizeC;
|
std::size_t _bucket = index / bucketSizeC;
|
||||||
size_t _index = index % bucketSizeC;
|
std::size_t _index = index % bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
return (mBucketList[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inline ElementT & operator[](const size_t index) const {
|
const inline ElementT & operator[](const std::size_t index) const {
|
||||||
size_t _bucket = index / bucketSizeC;
|
std::size_t _bucket = index / bucketSizeC;
|
||||||
size_t _index = index % bucketSizeC;
|
std::size_t _index = index % bucketSizeC;
|
||||||
return (mBucketList[_bucket][_index]);
|
return (mBucketList[_bucket][_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline ElementT & back() {
|
||||||
|
std::size_t _bucket = mCurrentSize / bucketSizeC;
|
||||||
|
std::size_t _index = mCurrentSize % bucketSizeC;
|
||||||
|
return (mBucketList[_bucket][_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const inline ElementT & back() const {
|
||||||
|
std::size_t _bucket = mCurrentSize / bucketSizeC;
|
||||||
|
std::size_t _index = mCurrentSize % bucketSizeC;
|
||||||
|
return (mBucketList[_bucket][_index]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DEALLOCATINGVECTOR_H_ */
|
#endif /* DEALLOCATINGVECTOR_H_ */
|
||||||
|
|||||||
@@ -21,18 +21,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef DYNAMICGRAPH_H_INCLUDED
|
#ifndef DYNAMICGRAPH_H_INCLUDED
|
||||||
#define DYNAMICGRAPH_H_INCLUDED
|
#define DYNAMICGRAPH_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
template< typename EdgeDataT>
|
||||||
class DynamicGraph {
|
class DynamicGraph {
|
||||||
public:
|
public:
|
||||||
typedef EdgeDataT EdgeData;
|
typedef EdgeDataT EdgeData;
|
||||||
typedef unsigned NodeIterator;
|
typedef uint32_t NodeIterator;
|
||||||
typedef unsigned EdgeIterator;
|
typedef uint32_t EdgeIterator;
|
||||||
|
|
||||||
class InputEdge {
|
class InputEdge {
|
||||||
public:
|
public:
|
||||||
@@ -47,20 +50,20 @@ class DynamicGraph {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Constructs an empty graph with a given number of nodes.
|
//Constructs an empty graph with a given number of nodes.
|
||||||
DynamicGraph( int nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
||||||
m_nodes.reserve( m_numNodes );
|
m_nodes.reserve( m_numNodes );
|
||||||
m_nodes.resize( m_numNodes );
|
m_nodes.resize( m_numNodes );
|
||||||
|
|
||||||
m_edges.reserve( m_numNodes * 1.1 );
|
m_edges.reserve( m_numNodes * 1.1 );
|
||||||
m_edges.resize( m_numNodes );
|
m_edges.resize( m_numNodes );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ContainerT>
|
template<class ContainerT>
|
||||||
DynamicGraph( const int nodes, const ContainerT &graph )
|
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
|
||||||
{
|
|
||||||
m_numNodes = nodes;
|
m_numNodes = nodes;
|
||||||
m_numEdges = ( EdgeIterator ) graph.size();
|
m_numEdges = ( EdgeIterator ) graph.size();
|
||||||
m_nodes.reserve( m_numNodes );
|
m_nodes.reserve( m_numNodes +1);
|
||||||
m_nodes.resize( m_numNodes );
|
m_nodes.resize( m_numNodes +1);
|
||||||
EdgeIterator edge = 0;
|
EdgeIterator edge = 0;
|
||||||
EdgeIterator position = 0;
|
EdgeIterator position = 0;
|
||||||
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
for ( NodeIterator node = 0; node < m_numNodes; ++node ) {
|
||||||
@@ -72,6 +75,7 @@ class DynamicGraph {
|
|||||||
m_nodes[node].edges = edge - lastEdge;
|
m_nodes[node].edges = edge - lastEdge;
|
||||||
position += m_nodes[node].edges;
|
position += m_nodes[node].edges;
|
||||||
}
|
}
|
||||||
|
m_nodes.back().firstEdge = position;
|
||||||
m_edges.reserve( position * 1.1 );
|
m_edges.reserve( position * 1.1 );
|
||||||
m_edges.resize( position );
|
m_edges.resize( position );
|
||||||
edge = 0;
|
edge = 0;
|
||||||
@@ -79,7 +83,10 @@ class DynamicGraph {
|
|||||||
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
||||||
m_edges[i].target = graph[edge].target;
|
m_edges[i].target = graph[edge].target;
|
||||||
m_edges[i].data = graph[edge].data;
|
m_edges[i].data = graph[edge].data;
|
||||||
GUARANTEE(graph[edge].data.distance > 0, "edge: " << edge << "(" << graph[edge].source << "," << graph[edge].target << ")=" << graph[edge].data.distance);
|
BOOST_ASSERT_MSG(
|
||||||
|
graph[edge].data.distance > 0,
|
||||||
|
"edge distance invalid"
|
||||||
|
);
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,50 +94,40 @@ class DynamicGraph {
|
|||||||
|
|
||||||
~DynamicGraph(){ }
|
~DynamicGraph(){ }
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const
|
uint32_t GetNumberOfNodes() const {
|
||||||
{
|
|
||||||
return m_numNodes;
|
return m_numNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const
|
uint32_t GetNumberOfEdges() const {
|
||||||
{
|
|
||||||
return m_numEdges;
|
return m_numEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator &n ) const
|
uint32_t GetOutDegree( const NodeIterator n ) const {
|
||||||
{
|
|
||||||
return m_nodes[n].edges;
|
return m_nodes[n].edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeIterator GetTarget( const EdgeIterator &e ) const
|
NodeIterator GetTarget( const EdgeIterator e ) const {
|
||||||
{
|
|
||||||
return NodeIterator( m_edges[e].target );
|
return NodeIterator( m_edges[e].target );
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeDataT &GetEdgeData( const EdgeIterator &e )
|
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
||||||
{
|
|
||||||
return m_edges[e].data;
|
return m_edges[e].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeDataT &GetEdgeData( const EdgeIterator &e ) const
|
const EdgeDataT &GetEdgeData( const EdgeIterator e ) const {
|
||||||
{
|
|
||||||
return m_edges[e].data;
|
return m_edges[e].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator &n ) const
|
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||||
{
|
|
||||||
//assert( EndEdges( n ) - EdgeIterator( _nodes[n].firstEdge ) <= 100 );
|
|
||||||
return EdgeIterator( m_nodes[n].firstEdge );
|
return EdgeIterator( m_nodes[n].firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator EndEdges( const NodeIterator &n ) const
|
EdgeIterator EndEdges( const NodeIterator n ) const {
|
||||||
{
|
|
||||||
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
|
return EdgeIterator( m_nodes[n].firstEdge + m_nodes[n].edges );
|
||||||
}
|
}
|
||||||
|
|
||||||
//adds an edge. Invalidates edge iterators for the source node
|
//adds an edge. Invalidates edge iterators for the source node
|
||||||
EdgeIterator InsertEdge( const NodeIterator &from, const NodeIterator &to, const EdgeDataT &data )
|
EdgeIterator InsertEdge( const NodeIterator from, const NodeIterator to, const EdgeDataT &data ) {
|
||||||
{
|
|
||||||
Node &node = m_nodes[from];
|
Node &node = m_nodes[from];
|
||||||
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
||||||
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
|
if ( newFirstEdge >= m_edges.size() || !isDummy( newFirstEdge ) ) {
|
||||||
@@ -139,7 +136,7 @@ class DynamicGraph {
|
|||||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
||||||
} else {
|
} else {
|
||||||
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
||||||
unsigned newSize = node.edges * 1.1 + 2;
|
uint32_t newSize = node.edges * 1.1 + 2;
|
||||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
||||||
EdgeIterator oldCapacity = m_edges.capacity();
|
EdgeIterator oldCapacity = m_edges.capacity();
|
||||||
if ( requiredCapacity >= oldCapacity ) {
|
if ( requiredCapacity >= oldCapacity ) {
|
||||||
@@ -164,20 +161,19 @@ class DynamicGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//removes an edge. Invalidates edge iterators for the source node
|
//removes an edge. Invalidates edge iterators for the source node
|
||||||
void DeleteEdge( const NodeIterator source, const EdgeIterator &e ) {
|
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
|
||||||
Node &node = m_nodes[source];
|
Node &node = m_nodes[source];
|
||||||
--m_numEdges;
|
--m_numEdges;
|
||||||
--node.edges;
|
--node.edges;
|
||||||
const unsigned last = node.firstEdge + node.edges;
|
const uint32_t last = node.firstEdge + node.edges;
|
||||||
//swap with last edge
|
//swap with last edge
|
||||||
m_edges[e] = m_edges[last];
|
m_edges[e] = m_edges[last];
|
||||||
makeDummy( last );
|
makeDummy( last );
|
||||||
}
|
}
|
||||||
|
|
||||||
//removes all edges (source,target)
|
//removes all edges (source,target)
|
||||||
int DeleteEdgesTo( const NodeIterator source, const NodeIterator target )
|
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
|
||||||
{
|
int32_t deleted = 0;
|
||||||
int deleted = 0;
|
|
||||||
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
||||||
if ( m_edges[i].target == target ) {
|
if ( m_edges[i].target == target ) {
|
||||||
do {
|
do {
|
||||||
@@ -196,10 +192,9 @@ class DynamicGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//searches for a specific edge
|
//searches for a specific edge
|
||||||
EdgeIterator FindEdge( const NodeIterator &from, const NodeIterator &to ) const
|
EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const {
|
||||||
{
|
|
||||||
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
|
for ( EdgeIterator i = BeginEdges( from ), iend = EndEdges( from ); i != iend; ++i ) {
|
||||||
if ( m_edges[i].target == to ) {
|
if ( to == m_edges[i].target ) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -208,13 +203,11 @@ class DynamicGraph {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool isDummy( EdgeIterator edge ) const
|
bool isDummy( const EdgeIterator edge ) const {
|
||||||
{
|
|
||||||
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
|
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeDummy( EdgeIterator edge )
|
void makeDummy( const EdgeIterator edge ) {
|
||||||
{
|
|
||||||
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
|
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +215,7 @@ class DynamicGraph {
|
|||||||
//index of the first edge
|
//index of the first edge
|
||||||
EdgeIterator firstEdge;
|
EdgeIterator firstEdge;
|
||||||
//amount of edges
|
//amount of edges
|
||||||
unsigned edges;
|
uint32_t edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Edge {
|
struct Edge {
|
||||||
@@ -233,9 +226,8 @@ class DynamicGraph {
|
|||||||
NodeIterator m_numNodes;
|
NodeIterator m_numNodes;
|
||||||
EdgeIterator m_numEdges;
|
EdgeIterator m_numEdges;
|
||||||
|
|
||||||
DeallocatingVector< Node > m_nodes;
|
std::vector< Node > m_nodes;
|
||||||
DeallocatingVector< Edge > m_edges;
|
DeallocatingVector< Edge > m_edges;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DYNAMICGRAPH_H_INCLUDED
|
#endif // DYNAMICGRAPH_H_INCLUDED
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GRIDEDGE_H_
|
|
||||||
#define GRIDEDGE_H_
|
|
||||||
|
|
||||||
#include "Coordinate.h"
|
|
||||||
|
|
||||||
struct _GridEdge {
|
|
||||||
_GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc) {}
|
|
||||||
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false) {}
|
|
||||||
NodeID edgeBasedNode;
|
|
||||||
NodeID nameID;
|
|
||||||
int weight;
|
|
||||||
_Coordinate startCoord;
|
|
||||||
_Coordinate targetCoord;
|
|
||||||
bool belongsToTinyComponent;
|
|
||||||
|
|
||||||
bool operator< ( const _GridEdge& right) const {
|
|
||||||
return edgeBasedNode < right.edgeBasedNode;
|
|
||||||
}
|
|
||||||
bool operator== ( const _GridEdge& right) const {
|
|
||||||
return edgeBasedNode == right.edgeBasedNode;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GridEntry {
|
|
||||||
GridEntry() : fileIndex(UINT_MAX), ramIndex(UINT_MAX){}
|
|
||||||
GridEntry(_GridEdge e, unsigned f, unsigned r) : edge(e), fileIndex(f), ramIndex(r) {}
|
|
||||||
_GridEdge edge;
|
|
||||||
unsigned fileIndex;
|
|
||||||
unsigned ramIndex;
|
|
||||||
bool operator< ( const GridEntry& right ) const {
|
|
||||||
return (edge.edgeBasedNode < right.edge.edgeBasedNode);
|
|
||||||
}
|
|
||||||
bool operator==( const GridEntry& right ) const {
|
|
||||||
return right.edge.edgeBasedNode == edge.edgeBasedNode;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CompareGridEdgeDataByFileIndex {
|
|
||||||
bool operator () (const GridEntry & a, const GridEntry & b) const {
|
|
||||||
return a.fileIndex < b.fileIndex;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CompareGridEdgeDataByRamIndex {
|
|
||||||
typedef GridEntry value_type;
|
|
||||||
|
|
||||||
bool operator () (const GridEntry & a, const GridEntry & b) const {
|
|
||||||
return a.ramIndex < b.ramIndex;
|
|
||||||
}
|
|
||||||
value_type max_value() {
|
|
||||||
GridEntry e;
|
|
||||||
e.ramIndex = (1024*1024) - 1;
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
value_type min_value() {
|
|
||||||
GridEntry e;
|
|
||||||
e.ramIndex = 0;
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* GRIDEDGE_H_ */
|
|
||||||
+15
-36
@@ -24,56 +24,35 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef HASHTABLE_H_
|
#ifndef HASHTABLE_H_
|
||||||
#define HASHTABLE_H_
|
#define HASHTABLE_H_
|
||||||
|
|
||||||
|
#include <boost/ref.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
template<typename keyT, typename valueT>
|
template<typename keyT, typename valueT>
|
||||||
class HashTable {
|
class HashTable : public boost::unordered_map<keyT, valueT> {
|
||||||
typedef boost::unordered_map<keyT, valueT> MyHashTable;
|
private:
|
||||||
|
typedef boost::unordered_map<keyT, valueT> super;
|
||||||
public:
|
public:
|
||||||
typedef typename boost::unordered_map<keyT, valueT>::const_iterator MyIterator;
|
HashTable() : super() { }
|
||||||
typedef MyIterator iterator;
|
|
||||||
HashTable() { }
|
HashTable(const unsigned size) : super(size) { }
|
||||||
HashTable(const unsigned size) {
|
|
||||||
table.resize(size);
|
|
||||||
}
|
|
||||||
inline void Add(const keyT& key, const valueT& value){
|
inline void Add(const keyT& key, const valueT& value){
|
||||||
table[key] = value;
|
super::insert(std::make_pair(key, value));
|
||||||
}
|
|
||||||
inline void Set(const keyT& key, const valueT& value){
|
|
||||||
table[key] = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline valueT Find(const keyT& key) const {
|
inline valueT Find(const keyT& key) const {
|
||||||
if(table.find(key) == table.end())
|
if(super::find(key) == super::end()) {
|
||||||
return valueT();
|
return valueT();
|
||||||
return table.find(key)->second;
|
}
|
||||||
|
return boost::ref(super::find(key)->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Holds(const keyT& key) const {
|
inline bool Holds(const keyT& key) const {
|
||||||
if(table.find(key) == table.end())
|
if(super::find(key) == super::end()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void EraseAll() {
|
|
||||||
if(table.size() > 0)
|
|
||||||
table.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline valueT operator[] (keyT key) const {
|
|
||||||
if(table.find(key) == table.end())
|
|
||||||
return valueT();
|
|
||||||
return table.find(key)->second;
|
|
||||||
}
|
|
||||||
inline unsigned Size() const {
|
|
||||||
return table.size();
|
|
||||||
}
|
|
||||||
MyIterator begin() const {
|
|
||||||
return table.begin();
|
|
||||||
}
|
|
||||||
MyIterator end() const {
|
|
||||||
return table.end();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MyHashTable table;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HASHTABLE_H_ */
|
#endif /* HASHTABLE_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HILBERTVALUE_H_
|
||||||
|
#define HILBERTVALUE_H_
|
||||||
|
|
||||||
|
#include "Coordinate.h"
|
||||||
|
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||||
|
|
||||||
|
class HilbertCode : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
static uint64_t GetHilbertNumberForCoordinate(
|
||||||
|
const FixedPointCoordinate & current_coordinate
|
||||||
|
) {
|
||||||
|
unsigned location[2];
|
||||||
|
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
|
||||||
|
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
|
||||||
|
|
||||||
|
TransposeCoordinate(location);
|
||||||
|
const uint64_t result = BitInterleaving(location[0], location[1]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
|
||||||
|
uint64_t result = 0;
|
||||||
|
for(int8_t index = 31; index >= 0; --index){
|
||||||
|
result |= (a >> index) & 1;
|
||||||
|
result <<= 1;
|
||||||
|
result |= (b >> index) & 1;
|
||||||
|
if(0 != index){
|
||||||
|
result <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void TransposeCoordinate( uint32_t * X) {
|
||||||
|
uint32_t M = 1 << (32-1), P, Q, t;
|
||||||
|
int i;
|
||||||
|
// Inverse undo
|
||||||
|
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||||
|
P=Q-1;
|
||||||
|
for( i = 0; i < 2; ++i ) {
|
||||||
|
if( X[i] & Q ) {
|
||||||
|
X[0] ^= P; // invert
|
||||||
|
} else {
|
||||||
|
t = (X[0]^X[i]) & P;
|
||||||
|
X[0] ^= t;
|
||||||
|
X[i] ^= t;
|
||||||
|
}
|
||||||
|
} // exchange
|
||||||
|
}
|
||||||
|
// Gray encode
|
||||||
|
for( i = 1; i < 2; ++i ) {
|
||||||
|
X[i] ^= X[i-1];
|
||||||
|
}
|
||||||
|
t=0;
|
||||||
|
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||||
|
if( X[2-1] & Q ) {
|
||||||
|
t ^= Q-1;
|
||||||
|
}
|
||||||
|
} //check if this for loop is wrong
|
||||||
|
for( i = 0; i < 2; ++i ) {
|
||||||
|
X[i] ^= t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HILBERTVALUE_H_ */
|
||||||
+74
-39
@@ -16,11 +16,13 @@ You should have received a copy of the GNU Affero General Public License
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EDGE_H
|
#ifndef EDGE_H
|
||||||
#define EDGE_H
|
#define EDGE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
class NodeBasedEdge {
|
class NodeBasedEdge {
|
||||||
@@ -40,12 +42,34 @@ public:
|
|||||||
return (source() < e.source());
|
return (source() < e.source());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Default constructor. target and weight are set to 0.*/
|
explicit NodeBasedEdge(
|
||||||
NodeBasedEdge() :
|
NodeID s,
|
||||||
_source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false) { assert(false); } //shall not be used.
|
NodeID t,
|
||||||
|
NodeID n,
|
||||||
explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar) :
|
EdgeWeight w,
|
||||||
_source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar) { if(ty < 0) {ERR("Type: " << ty);}; }
|
bool f,
|
||||||
|
bool b,
|
||||||
|
short ty,
|
||||||
|
bool ra,
|
||||||
|
bool ig,
|
||||||
|
bool ar,
|
||||||
|
bool cf
|
||||||
|
) : _source(s),
|
||||||
|
_target(t),
|
||||||
|
_name(n),
|
||||||
|
_weight(w),
|
||||||
|
forward(f),
|
||||||
|
backward(b),
|
||||||
|
_type(ty),
|
||||||
|
_roundabout(ra),
|
||||||
|
_ignoreInGrid(ig),
|
||||||
|
_accessRestricted(ar),
|
||||||
|
_contraFlow(cf)
|
||||||
|
{
|
||||||
|
if(ty < 0) {
|
||||||
|
throw OSRMException("negative edge type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NodeID target() const {return _target; }
|
NodeID target() const {return _target; }
|
||||||
NodeID source() const {return _source; }
|
NodeID source() const {return _source; }
|
||||||
@@ -59,6 +83,7 @@ public:
|
|||||||
bool isRoundabout() const { return _roundabout; }
|
bool isRoundabout() const { return _roundabout; }
|
||||||
bool ignoreInGrid() const { return _ignoreInGrid; }
|
bool ignoreInGrid() const { return _ignoreInGrid; }
|
||||||
bool isAccessRestricted() const { return _accessRestricted; }
|
bool isAccessRestricted() const { return _accessRestricted; }
|
||||||
|
bool isContraFlow() const { return _contraFlow; }
|
||||||
|
|
||||||
NodeID _source;
|
NodeID _source;
|
||||||
NodeID _target;
|
NodeID _target;
|
||||||
@@ -70,6 +95,13 @@ public:
|
|||||||
bool _roundabout;
|
bool _roundabout;
|
||||||
bool _ignoreInGrid;
|
bool _ignoreInGrid;
|
||||||
bool _accessRestricted;
|
bool _accessRestricted;
|
||||||
|
bool _contraFlow;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Default constructor. target and weight are set to 0.*/
|
||||||
|
NodeBasedEdge() :
|
||||||
|
_source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EdgeBasedEdge {
|
class EdgeBasedEdge {
|
||||||
@@ -91,43 +123,46 @@ public:
|
|||||||
|
|
||||||
template<class EdgeT>
|
template<class EdgeT>
|
||||||
EdgeBasedEdge(const EdgeT & myEdge ) :
|
EdgeBasedEdge(const EdgeT & myEdge ) :
|
||||||
_source(myEdge.source),
|
m_source(myEdge.source),
|
||||||
_target(myEdge.target),
|
m_target(myEdge.target),
|
||||||
_edgeID(myEdge.data.via),
|
m_edgeID(myEdge.data.via),
|
||||||
// _nameID1(myEdge.data.nameID),
|
m_weight(myEdge.data.distance),
|
||||||
_weight(myEdge.data.distance),
|
m_forward(myEdge.data.forward),
|
||||||
_forward(myEdge.data.forward),
|
m_backward(myEdge.data.backward)
|
||||||
_backward(myEdge.data.backward)//,
|
{ }
|
||||||
// _turnInstruction(myEdge.data.turnInstruction)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/** Default constructor. target and weight are set to 0.*/
|
/** Default constructor. target and weight are set to 0.*/
|
||||||
EdgeBasedEdge() :
|
EdgeBasedEdge() :
|
||||||
_source(0), _target(0), _edgeID(0), _weight(0), _forward(false), _backward(false) { }
|
m_source(0),
|
||||||
|
m_target(0),
|
||||||
|
m_edgeID(0),
|
||||||
|
m_weight(0),
|
||||||
|
m_forward(false),
|
||||||
|
m_backward(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
explicit EdgeBasedEdge(NodeID s, NodeID t, NodeID v, EdgeWeight w, bool f, bool b) :
|
explicit EdgeBasedEdge(const NodeID s, const NodeID t, const NodeID v, const EdgeWeight w, const bool f, const bool b) :
|
||||||
_source(s), _target(t), _edgeID(v), _weight(w), _forward(f), _backward(b){}
|
m_source(s),
|
||||||
|
m_target(t),
|
||||||
|
m_edgeID(v),
|
||||||
|
m_weight(w),
|
||||||
|
m_forward(f),
|
||||||
|
m_backward(b)
|
||||||
|
{}
|
||||||
|
|
||||||
NodeID target() const {return _target; }
|
NodeID target() const {return m_target; }
|
||||||
NodeID source() const {return _source; }
|
NodeID source() const {return m_source; }
|
||||||
EdgeWeight weight() const {return _weight; }
|
EdgeWeight weight() const {return m_weight; }
|
||||||
NodeID id() const { return _edgeID; }
|
NodeID id() const { return m_edgeID; }
|
||||||
bool isBackward() const { return _backward; }
|
bool isBackward() const { return m_backward; }
|
||||||
bool isForward() const { return _forward; }
|
bool isForward() const { return m_forward; }
|
||||||
|
private:
|
||||||
NodeID _source;
|
NodeID m_source;
|
||||||
NodeID _target;
|
NodeID m_target;
|
||||||
NodeID _edgeID;
|
NodeID m_edgeID;
|
||||||
EdgeWeight _weight:30;
|
EdgeWeight m_weight:30;
|
||||||
bool _forward:1;
|
bool m_forward:1;
|
||||||
bool _backward:1;
|
bool m_backward:1;
|
||||||
};
|
|
||||||
|
|
||||||
struct MinimalEdgeData {
|
|
||||||
public:
|
|
||||||
EdgeWeight distance;
|
|
||||||
bool forward;
|
|
||||||
bool backward;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NodeBasedEdge ImportEdge;
|
typedef NodeBasedEdge ImportEdge;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef IMPORTNODE_H_
|
#ifndef IMPORTNODE_H_
|
||||||
#define IMPORTNODE_H_
|
#define IMPORTNODE_H_
|
||||||
|
|
||||||
#include "NodeCoords.h"
|
#include "QueryNode.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -44,9 +44,9 @@ struct _Node : NodeInfo{
|
|||||||
|
|
||||||
struct ImportNode : public _Node {
|
struct ImportNode : public _Node {
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
|
|
||||||
inline void Clear() {
|
inline void Clear() {
|
||||||
keyVals.EraseAll();
|
keyVals.clear();
|
||||||
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
|
lat = 0; lon = 0; id = 0; bollard = false; trafficLight = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,21 +43,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) {
|
|||||||
return read;
|
return read;
|
||||||
} else if(BZ_STREAM_END == context->error) {
|
} else if(BZ_STREAM_END == context->error) {
|
||||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||||
if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadGetUnused" << endl; exit(-1);};
|
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <<std::endl; exit(-1);};
|
||||||
unusedTmp = (char*)unusedTmpVoid;
|
unusedTmp = (char*)unusedTmpVoid;
|
||||||
for(int i=0;i<context->nUnused;i++) {
|
for(int i=0;i<context->nUnused;i++) {
|
||||||
context->unused[i] = unusedTmp[i];
|
context->unused[i] = unusedTmp[i];
|
||||||
}
|
}
|
||||||
BZ2_bzReadClose(&context->error, context->bz2);
|
BZ2_bzReadClose(&context->error, context->bz2);
|
||||||
if(BZ_OK != context->error) { cerr << "Could not BZ2_bzReadClose" << endl; exit(-1);};
|
if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <<std::endl; exit(-1);};
|
||||||
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||||
if(0 == context->nUnused && feof(context->file)) {
|
if(0 == context->nUnused && feof(context->file)) {
|
||||||
return read;
|
return read;
|
||||||
} else {
|
} else {
|
||||||
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||||
if(NULL == context->bz2){ cerr << "Could not open file" << endl; exit(-1);};
|
if(NULL == context->bz2){std::cerr << "Could not open file" <<std::endl; exit(-1);};
|
||||||
}
|
}
|
||||||
} else { cerr << "Could not read bz2 file" << endl; exit(-1); }
|
} else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); }
|
||||||
}
|
}
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ xmlTextReaderPtr inputReaderFactory( const char* name )
|
|||||||
{
|
{
|
||||||
std::string inputName(name);
|
std::string inputName(name);
|
||||||
|
|
||||||
if(inputName.find(".osm.bz2")!=string::npos)
|
if(inputName.find(".osm.bz2")!=std::string::npos)
|
||||||
{
|
{
|
||||||
BZ2Context* context = new BZ2Context();
|
BZ2Context* context = new BZ2Context();
|
||||||
context->error = false;
|
context->error = false;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
open source routing machine
|
||||||
Copyright (C) Dennis Luxen, 2010
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
@@ -16,13 +16,23 @@ You should have received a copy of the GNU Affero General Public License
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SERVERCONFIGURATION_H_
|
#ifndef MERCATORUTIL_H_
|
||||||
#define SERVERCONFIGURATION_H_
|
#define MERCATORUTIL_H_
|
||||||
|
|
||||||
#include "../Util/BaseConfiguration.h"
|
#include <cmath>
|
||||||
|
|
||||||
typedef BaseConfiguration ServerConfiguration;
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SERVERCONFIGURATION_H_ */
|
inline double y2lat(double a) {
|
||||||
|
return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double lat2y(double a) {
|
||||||
|
return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MERCATORUTIL_H_ */
|
||||||
@@ -1,594 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NNGRID_H_
|
|
||||||
#define NNGRID_H_
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
|
||||||
#include <cfloat>
|
|
||||||
#include <cmath>
|
|
||||||
#include <fstream>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
#include <stxxl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <math.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include "DeallocatingVector.h"
|
|
||||||
//#include "ExtractorStructs.h"
|
|
||||||
#include "GridEdge.h"
|
|
||||||
#include "Percent.h"
|
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "Util.h"
|
|
||||||
#include "StaticGraph.h"
|
|
||||||
#include "../Algorithms/Bresenham.h"
|
|
||||||
|
|
||||||
namespace NNGrid{
|
|
||||||
|
|
||||||
static boost::thread_specific_ptr<std::ifstream> localStream;
|
|
||||||
|
|
||||||
template<bool WriteAccess = false>
|
|
||||||
class NNGrid {
|
|
||||||
public:
|
|
||||||
NNGrid() /*: cellCache(500), fileCache(500)*/ {
|
|
||||||
ramIndexTable.resize((1024*1024), ULONG_MAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
NNGrid(const char* rif, const char* _i) {
|
|
||||||
if(WriteAccess) {
|
|
||||||
ERR("Not available in Write mode");
|
|
||||||
}
|
|
||||||
iif = std::string(_i);
|
|
||||||
ramIndexTable.resize((1024*1024), ULONG_MAX);
|
|
||||||
ramInFile.open(rif, std::ios::in | std::ios::binary);
|
|
||||||
if(!ramInFile) { ERR(rif << " not found"); }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~NNGrid() {
|
|
||||||
if(ramInFile.is_open()) ramInFile.close();
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
if (WriteAccess) {
|
|
||||||
entries.clear();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(localStream.get() && localStream->is_open()) {
|
|
||||||
localStream->close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenIndexFiles() {
|
|
||||||
assert(ramInFile.is_open());
|
|
||||||
ramInFile.read(static_cast<char*>(static_cast<void*>(&ramIndexTable[0]) ), sizeof(unsigned long)*1024*1024);
|
|
||||||
ramInFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
template<typename EdgeT>
|
|
||||||
inline void ConstructGrid(DeallocatingVector<EdgeT> & edgeList, char * ramIndexOut, char * fileIndexOut) {
|
|
||||||
//TODO: Implement this using STXXL-Streams
|
|
||||||
Percent p(edgeList.size());
|
|
||||||
BOOST_FOREACH(EdgeT & edge, edgeList) {
|
|
||||||
p.printIncrement();
|
|
||||||
if(edge.ignoreInGrid)
|
|
||||||
continue;
|
|
||||||
int slat = 100000*lat2y(edge.lat1/100000.);
|
|
||||||
int slon = edge.lon1;
|
|
||||||
int tlat = 100000*lat2y(edge.lat2/100000.);
|
|
||||||
int tlon = edge.lon2;
|
|
||||||
AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent ) );
|
|
||||||
}
|
|
||||||
double timestamp = get_timestamp();
|
|
||||||
//create index file on disk, old one is over written
|
|
||||||
indexOutFile.open(fileIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
|
|
||||||
//sort entries
|
|
||||||
stxxl::sort(entries.begin(), entries.end(), CompareGridEdgeDataByRamIndex(), 1024*1024*1024);
|
|
||||||
INFO("finished sorting after " << (get_timestamp() - timestamp) << "s");
|
|
||||||
std::vector<GridEntry> entriesInFileWithRAMSameIndex;
|
|
||||||
unsigned indexInRamTable = entries.begin()->ramIndex;
|
|
||||||
unsigned long lastPositionInIndexFile = 0;
|
|
||||||
cout << "writing data ..." << flush;
|
|
||||||
p.reinit(entries.size());
|
|
||||||
boost::unordered_map< unsigned, unsigned > cellMap(1024);
|
|
||||||
BOOST_FOREACH(GridEntry & gridEntry, entries) {
|
|
||||||
p.printIncrement();
|
|
||||||
if(gridEntry.ramIndex != indexInRamTable) {
|
|
||||||
cellMap.clear();
|
|
||||||
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
|
|
||||||
|
|
||||||
unsigned numberOfBytesInCell = FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
|
|
||||||
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
|
|
||||||
lastPositionInIndexFile += numberOfBytesInCell;
|
|
||||||
entriesInFileWithRAMSameIndex.clear();
|
|
||||||
indexInRamTable = gridEntry.ramIndex;
|
|
||||||
}
|
|
||||||
entriesInFileWithRAMSameIndex.push_back(gridEntry);
|
|
||||||
}
|
|
||||||
cellMap.clear();
|
|
||||||
BuildCellIndexToFileIndexMap(indexInRamTable, cellMap);
|
|
||||||
/*unsigned numberOfBytesInCell = */FillCell(entriesInFileWithRAMSameIndex, lastPositionInIndexFile, cellMap);
|
|
||||||
ramIndexTable[indexInRamTable] = lastPositionInIndexFile;
|
|
||||||
entriesInFileWithRAMSameIndex.clear();
|
|
||||||
std::vector<GridEntry>().swap(entriesInFileWithRAMSameIndex);
|
|
||||||
assert(entriesInFileWithRAMSameIndex.size() == 0);
|
|
||||||
//close index file
|
|
||||||
indexOutFile.close();
|
|
||||||
|
|
||||||
//Serialize RAM Index
|
|
||||||
ofstream ramFile(ramIndexOut, std::ios::out | std::ios::binary | std::ios::trunc);
|
|
||||||
//write 4 MB of index Table in RAM
|
|
||||||
ramFile.write((char *)&ramIndexTable[0], sizeof(unsigned long)*1024*1024 );
|
|
||||||
//close ram index file
|
|
||||||
ramFile.close();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
|
|
||||||
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) {
|
|
||||||
bool ignoreTinyComponents = (zoomLevel <= 14);
|
|
||||||
// INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no"));
|
|
||||||
// double time1 = get_timestamp();
|
|
||||||
bool foundNode = false;
|
|
||||||
const _Coordinate startCoord(100000*(lat2y(static_cast<double>(location.lat)/100000.)), location.lon);
|
|
||||||
/** search for point on edge close to source */
|
|
||||||
const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
|
|
||||||
std::vector<_GridEdge> candidates;
|
|
||||||
const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768);
|
|
||||||
for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) {
|
|
||||||
for(int i = -1; i < 2; ++i){
|
|
||||||
// unsigned oldSize = candidates.size();
|
|
||||||
GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates);
|
|
||||||
// INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// INFO("looked up " << candidates.size());
|
|
||||||
_GridEdge smallestEdge;
|
|
||||||
_Coordinate tmp, edgeStartCoord, edgeEndCoord;
|
|
||||||
double dist = numeric_limits<double>::max();
|
|
||||||
double r, tmpDist;
|
|
||||||
|
|
||||||
BOOST_FOREACH(_GridEdge candidate, candidates) {
|
|
||||||
if(candidate.belongsToTinyComponent && ignoreTinyComponents)
|
|
||||||
continue;
|
|
||||||
r = 0.;
|
|
||||||
tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
|
|
||||||
// INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist );
|
|
||||||
// INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist);
|
|
||||||
if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) {
|
|
||||||
// INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no"));
|
|
||||||
dist = tmpDist;
|
|
||||||
resultNode.edgeBasedNode = candidate.edgeBasedNode;
|
|
||||||
resultNode.nodeBasedEdgeNameID = candidate.nameID;
|
|
||||||
resultNode.weight1 = candidate.weight;
|
|
||||||
resultNode.weight2 = INT_MAX;
|
|
||||||
resultNode.location.lat = tmp.lat;
|
|
||||||
resultNode.location.lon = tmp.lon;
|
|
||||||
edgeStartCoord = candidate.startCoord;
|
|
||||||
edgeEndCoord = candidate.targetCoord;
|
|
||||||
foundNode = true;
|
|
||||||
smallestEdge = candidate;
|
|
||||||
//} else if(tmpDist < dist) {
|
|
||||||
//INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist));
|
|
||||||
} else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast<int>(candidate.edgeBasedNode)-static_cast<int>(resultNode.edgeBasedNode) ) && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) {
|
|
||||||
resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode);
|
|
||||||
resultNode.weight2 = candidate.weight;
|
|
||||||
//INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint);
|
|
||||||
// INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
|
|
||||||
// INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint));
|
|
||||||
// assert(!resultNode.isBidirected() || (resultNode.weight1 == resultNode.weight2));
|
|
||||||
// if(resultNode.weight1 != resultNode.weight2) {
|
|
||||||
// INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2);
|
|
||||||
// INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location);
|
|
||||||
double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0);
|
|
||||||
resultNode.location.lat = round(100000.*(y2lat(static_cast<double>(resultNode.location.lat)/100000.)));
|
|
||||||
// INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord));
|
|
||||||
//Hack to fix rounding errors and wandering via nodes.
|
|
||||||
if(std::abs(location.lon - resultNode.location.lon) == 1)
|
|
||||||
resultNode.location.lon = location.lon;
|
|
||||||
if(std::abs(location.lat - resultNode.location.lat) == 1)
|
|
||||||
resultNode.location.lat = location.lat;
|
|
||||||
|
|
||||||
resultNode.weight1 *= ratio;
|
|
||||||
if(INT_MAX != resultNode.weight2) {
|
|
||||||
resultNode.weight2 -= resultNode.weight1;
|
|
||||||
}
|
|
||||||
resultNode.ratio = ratio;
|
|
||||||
// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio);
|
|
||||||
// INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord);
|
|
||||||
// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--");
|
|
||||||
// double time2 = get_timestamp();
|
|
||||||
// INFO("NN-Lookup in " << 1000*(time2-time1) << "ms");
|
|
||||||
return foundNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) {
|
|
||||||
routingStarts.Reset();
|
|
||||||
return (FindPhantomNodeForCoordinate( start, routingStarts.startPhantom, zoomLevel) &&
|
|
||||||
FindPhantomNodeForCoordinate( target, routingStarts.targetPhantom, zoomLevel) );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FindNearestCoordinateOnEdgeInNodeBasedGraph(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate, unsigned zoomLevel = 18) {
|
|
||||||
PhantomNode resultNode;
|
|
||||||
bool foundNode = FindPhantomNodeForCoordinate(inputCoordinate, resultNode, zoomLevel);
|
|
||||||
outputCoordinate = resultNode.location;
|
|
||||||
return foundNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FindNearestPointOnEdge(const _Coordinate& inputCoordinate, _Coordinate& outputCoordinate) {
|
|
||||||
_Coordinate startCoord(100000*(lat2y(static_cast<double>(inputCoordinate.lat)/100000.)), inputCoordinate.lon);
|
|
||||||
unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon);
|
|
||||||
|
|
||||||
std::vector<_GridEdge> candidates;
|
|
||||||
boost::unordered_map< unsigned, unsigned > cellMap;
|
|
||||||
for(int j = -32768; j < (32768+1); j+=32768) {
|
|
||||||
for(int i = -1; i < 2; ++i) {
|
|
||||||
GetContentsOfFileBucket(fileIndex+i+j, candidates, cellMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_Coordinate tmp;
|
|
||||||
double dist = (std::numeric_limits<double>::max)();
|
|
||||||
BOOST_FOREACH(_GridEdge candidate, candidates) {
|
|
||||||
double r = 0.;
|
|
||||||
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
|
|
||||||
if(tmpDist < dist) {
|
|
||||||
dist = tmpDist;
|
|
||||||
outputCoordinate.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
|
|
||||||
outputCoordinate.lon = tmp.lon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
inline unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const {
|
|
||||||
unsigned lineBase = ramIndex/1024;
|
|
||||||
lineBase = lineBase*32*32768;
|
|
||||||
unsigned columnBase = ramIndex%1024;
|
|
||||||
columnBase=columnBase*32;
|
|
||||||
for (int i = 0;i < 32;++i) {
|
|
||||||
for (int j = 0;j < 32;++j) {
|
|
||||||
const unsigned localFileIndex = lineBase + i * 32768 + columnBase + j;
|
|
||||||
if(localFileIndex == fileIndex) {
|
|
||||||
unsigned cellIndex = i * 32 + j;
|
|
||||||
return cellIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return UINT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BuildCellIndexToFileIndexMap(const unsigned ramIndex, boost::unordered_map<unsigned, unsigned >& cellMap){
|
|
||||||
unsigned lineBase = ramIndex/1024;
|
|
||||||
lineBase = lineBase*32*32768;
|
|
||||||
unsigned columnBase = ramIndex%1024;
|
|
||||||
columnBase=columnBase*32;
|
|
||||||
std::vector<std::pair<unsigned, unsigned> >insertionVector(1024);
|
|
||||||
for (int i = 0;i < 32;++i) {
|
|
||||||
for (int j = 0;j < 32;++j) {
|
|
||||||
unsigned fileIndex = lineBase + i * 32768 + columnBase + j;
|
|
||||||
unsigned cellIndex = i * 32 + j;
|
|
||||||
insertionVector[i * 32 + j] = std::make_pair(fileIndex, cellIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cellMap.insert(insertionVector.begin(), insertionVector.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool DoubleEpsilonCompare(const double d1, const double d2) {
|
|
||||||
return (std::fabs(d1 - d2) < FLT_EPSILON);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, const unsigned long fileOffset, boost::unordered_map< unsigned, unsigned > & cellMap ) {
|
|
||||||
std::vector<char> tmpBuffer(32*32*4096,0);
|
|
||||||
unsigned long indexIntoTmpBuffer = 0;
|
|
||||||
unsigned numberOfWrittenBytes = 0;
|
|
||||||
assert(indexOutFile.is_open());
|
|
||||||
|
|
||||||
std::vector<unsigned long> cellIndex(32*32,ULONG_MAX);
|
|
||||||
|
|
||||||
for(unsigned i = 0; i < entriesWithSameRAMIndex.size() -1; ++i) {
|
|
||||||
assert(entriesWithSameRAMIndex[i].ramIndex== entriesWithSameRAMIndex[i+1].ramIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
//sort & unique
|
|
||||||
std::sort(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end(), CompareGridEdgeDataByFileIndex());
|
|
||||||
// entriesWithSameRAMIndex.erase(std::unique(entriesWithSameRAMIndex.begin(), entriesWithSameRAMIndex.end()), entriesWithSameRAMIndex.end());
|
|
||||||
|
|
||||||
//traverse each file bucket and write its contents to disk
|
|
||||||
std::vector<GridEntry> entriesWithSameFileIndex;
|
|
||||||
unsigned fileIndex = entriesWithSameRAMIndex.begin()->fileIndex;
|
|
||||||
|
|
||||||
BOOST_FOREACH(GridEntry & gridEntry, entriesWithSameRAMIndex) {
|
|
||||||
assert(cellMap.find(gridEntry.fileIndex) != cellMap.end() ); //asserting that file index belongs to cell index
|
|
||||||
if(gridEntry.fileIndex != fileIndex) {
|
|
||||||
// start in cellIndex vermerken
|
|
||||||
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
|
|
||||||
int localCellIndex = cellMap.find(localFileIndex)->second;
|
|
||||||
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
|
|
||||||
|
|
||||||
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
|
|
||||||
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
|
|
||||||
fileIndex = gridEntry.fileIndex;
|
|
||||||
}
|
|
||||||
entriesWithSameFileIndex.push_back(gridEntry);
|
|
||||||
}
|
|
||||||
assert(cellMap.find(entriesWithSameFileIndex.begin()->fileIndex) != cellMap.end());
|
|
||||||
int localFileIndex = entriesWithSameFileIndex.begin()->fileIndex;
|
|
||||||
int localCellIndex = cellMap.find(localFileIndex)->second;
|
|
||||||
|
|
||||||
cellIndex[localCellIndex] = indexIntoTmpBuffer + fileOffset;
|
|
||||||
indexIntoTmpBuffer += FlushEntriesWithSameFileIndexToBuffer(entriesWithSameFileIndex, tmpBuffer, indexIntoTmpBuffer);
|
|
||||||
|
|
||||||
assert(entriesWithSameFileIndex.size() == 0);
|
|
||||||
indexOutFile.write(static_cast<char*>(static_cast<void*>(&cellIndex[0])),32*32*sizeof(unsigned long));
|
|
||||||
numberOfWrittenBytes += 32*32*sizeof(unsigned long);
|
|
||||||
|
|
||||||
//write contents of tmpbuffer to disk
|
|
||||||
indexOutFile.write(&tmpBuffer[0], indexIntoTmpBuffer*sizeof(char));
|
|
||||||
numberOfWrittenBytes += indexIntoTmpBuffer*sizeof(char);
|
|
||||||
|
|
||||||
return numberOfWrittenBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned FlushEntriesWithSameFileIndexToBuffer( std::vector<GridEntry> &vectorWithSameFileIndex, std::vector<char> & tmpBuffer, const unsigned long index) const {
|
|
||||||
sort( vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end() );
|
|
||||||
vectorWithSameFileIndex.erase(unique(vectorWithSameFileIndex.begin(), vectorWithSameFileIndex.end()), vectorWithSameFileIndex.end());
|
|
||||||
const unsigned lengthOfBucket = vectorWithSameFileIndex.size();
|
|
||||||
tmpBuffer.resize(tmpBuffer.size()+(sizeof(_GridEdge)*lengthOfBucket) + sizeof(unsigned) );
|
|
||||||
unsigned counter = 0;
|
|
||||||
|
|
||||||
for(unsigned i = 0; i < vectorWithSameFileIndex.size()-1; ++i) {
|
|
||||||
assert( vectorWithSameFileIndex[i].fileIndex == vectorWithSameFileIndex[i+1].fileIndex );
|
|
||||||
assert( vectorWithSameFileIndex[i].ramIndex == vectorWithSameFileIndex[i+1].ramIndex );
|
|
||||||
}
|
|
||||||
|
|
||||||
//write length of bucket
|
|
||||||
memcpy((char*)&(tmpBuffer[index+counter]), (char*)&lengthOfBucket, sizeof(lengthOfBucket));
|
|
||||||
counter += sizeof(lengthOfBucket);
|
|
||||||
|
|
||||||
BOOST_FOREACH(const GridEntry & entry, vectorWithSameFileIndex) {
|
|
||||||
char * data = (char*)&(entry.edge);
|
|
||||||
memcpy(static_cast<char*>(static_cast<void*>(&(tmpBuffer[index+counter]) )), data, sizeof(entry.edge));
|
|
||||||
counter += sizeof(entry.edge);
|
|
||||||
}
|
|
||||||
//Freeing data
|
|
||||||
vectorWithSameFileIndex.clear();
|
|
||||||
return counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GetContentsOfFileBucketEnumerated(const unsigned fileIndex, std::vector<_GridEdge>& result) const {
|
|
||||||
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
|
|
||||||
unsigned long startIndexInFile = ramIndexTable[ramIndex];
|
|
||||||
if(startIndexInFile == ULONG_MAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
unsigned enumeratedIndex = GetCellIndexFromRAMAndFileIndex(ramIndex, fileIndex);
|
|
||||||
|
|
||||||
if(!localStream.get() || !localStream->is_open()) {
|
|
||||||
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
|
|
||||||
}
|
|
||||||
if(!localStream->good()) {
|
|
||||||
localStream->clear(std::ios::goodbit);
|
|
||||||
DEBUG("Resetting stale filestream");
|
|
||||||
}
|
|
||||||
|
|
||||||
//only read the single necessary cell index
|
|
||||||
localStream->seekg(startIndexInFile+(enumeratedIndex*sizeof(unsigned long)));
|
|
||||||
unsigned long fetchedIndex = 0;
|
|
||||||
localStream->read(static_cast<char*>( static_cast<void*>(&fetchedIndex)), sizeof(unsigned long));
|
|
||||||
|
|
||||||
if(fetchedIndex == ULONG_MAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const unsigned long position = fetchedIndex + 32*32*sizeof(unsigned long) ;
|
|
||||||
|
|
||||||
unsigned lengthOfBucket;
|
|
||||||
unsigned currentSizeOfResult = result.size();
|
|
||||||
localStream->seekg(position);
|
|
||||||
localStream->read(static_cast<char*>( static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
|
|
||||||
result.resize(currentSizeOfResult+lengthOfBucket);
|
|
||||||
localStream->read(static_cast<char*>( static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GetContentsOfFileBucket(const unsigned fileIndex, std::vector<_GridEdge>& result, boost::unordered_map< unsigned, unsigned> & cellMap) {
|
|
||||||
unsigned ramIndex = GetRAMIndexFromFileIndex(fileIndex);
|
|
||||||
unsigned long startIndexInFile = ramIndexTable[ramIndex];
|
|
||||||
if(startIndexInFile == ULONG_MAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long cellIndex[32*32];
|
|
||||||
|
|
||||||
cellMap.clear();
|
|
||||||
BuildCellIndexToFileIndexMap(ramIndex, cellMap);
|
|
||||||
if(!localStream.get() || !localStream->is_open()) {
|
|
||||||
localStream.reset(new std::ifstream(iif.c_str(), std::ios::in | std::ios::binary));
|
|
||||||
}
|
|
||||||
if(!localStream->good()) {
|
|
||||||
localStream->clear(std::ios::goodbit);
|
|
||||||
DEBUG("Resetting stale filestream");
|
|
||||||
}
|
|
||||||
|
|
||||||
localStream->seekg(startIndexInFile);
|
|
||||||
localStream->read(static_cast<char*>(static_cast<void*>( cellIndex)), 32*32*sizeof(unsigned long));
|
|
||||||
assert(cellMap.find(fileIndex) != cellMap.end());
|
|
||||||
if(cellIndex[cellMap[fileIndex]] == ULONG_MAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const unsigned long position = cellIndex[cellMap[fileIndex]] + 32*32*sizeof(unsigned long) ;
|
|
||||||
|
|
||||||
unsigned lengthOfBucket;
|
|
||||||
unsigned currentSizeOfResult = result.size();
|
|
||||||
localStream->seekg(position);
|
|
||||||
localStream->read(static_cast<char*>(static_cast<void*>(&(lengthOfBucket))), sizeof(unsigned));
|
|
||||||
result.resize(currentSizeOfResult+lengthOfBucket);
|
|
||||||
localStream->read(static_cast<char*>(static_cast<void*>(&result[currentSizeOfResult])), lengthOfBucket*sizeof(_GridEdge));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ROUTED
|
|
||||||
inline void AddEdge(const _GridEdge & edge) {
|
|
||||||
std::vector<BresenhamPixel> indexList;
|
|
||||||
GetListOfIndexesForEdgeAndGridSize(edge.startCoord, edge.targetCoord, indexList);
|
|
||||||
for(unsigned i = 0; i < indexList.size(); ++i) {
|
|
||||||
entries.push_back(GridEntry(edge, indexList[i].first, indexList[i].second));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
inline double ComputeDistance(const _Coordinate& inputPoint, const _Coordinate& source, const _Coordinate& target, _Coordinate& nearest, double *r) {
|
|
||||||
// INFO("comparing point " << inputPoint << " to edge [" << source << "-" << target << "]");
|
|
||||||
const double x = static_cast<double>(inputPoint.lat);
|
|
||||||
const double y = static_cast<double>(inputPoint.lon);
|
|
||||||
const double a = static_cast<double>(source.lat);
|
|
||||||
const double b = static_cast<double>(source.lon);
|
|
||||||
const double c = static_cast<double>(target.lat);
|
|
||||||
const double d = static_cast<double>(target.lon);
|
|
||||||
double p,q,mX,nY;
|
|
||||||
// INFO("x=" << x << ", y=" << y << ", a=" << a << ", b=" << b << ", c=" << c << ", d=" << d);
|
|
||||||
if(fabs(a-c) > FLT_EPSILON){
|
|
||||||
const double m = (d-b)/(c-a); // slope
|
|
||||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
|
||||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
|
||||||
q = b + m*(p - a);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
p = c;
|
|
||||||
q = y;
|
|
||||||
}
|
|
||||||
nY = (d*p - c*q)/(a*d - b*c);
|
|
||||||
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we neednot calculate the values of m an n as we are just interested in the ratio
|
|
||||||
// INFO("p=" << p << ", q=" << q << ", nY=" << nY << ", mX=" << mX);
|
|
||||||
if(std::isnan(mX)) {
|
|
||||||
*r = (target == inputPoint) ? 1. : 0.;
|
|
||||||
} else {
|
|
||||||
*r = mX;
|
|
||||||
}
|
|
||||||
// INFO("r=" << *r);
|
|
||||||
if(*r<=0.){
|
|
||||||
nearest.lat = source.lat;
|
|
||||||
nearest.lon = source.lon;
|
|
||||||
// INFO("a returning distance " << ((b - y)*(b - y) + (a - x)*(a - x)))
|
|
||||||
return ((b - y)*(b - y) + (a - x)*(a - x));
|
|
||||||
}
|
|
||||||
else if(*r >= 1.){
|
|
||||||
nearest.lat = target.lat;
|
|
||||||
nearest.lon = target.lon;
|
|
||||||
// INFO("b returning distance " << ((d - y)*(d - y) + (c - x)*(c - x)))
|
|
||||||
|
|
||||||
return ((d - y)*(d - y) + (c - x)*(c - x));
|
|
||||||
}
|
|
||||||
// point lies in between
|
|
||||||
nearest.lat = p;
|
|
||||||
nearest.lon = q;
|
|
||||||
// INFO("c returning distance " << (p-x)*(p-x) + (q-y)*(q-y))
|
|
||||||
|
|
||||||
return (p-x)*(p-x) + (q-y)*(q-y);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void GetListOfIndexesForEdgeAndGridSize(const _Coordinate& start, const _Coordinate& target, std::vector<BresenhamPixel> &indexList) const {
|
|
||||||
double lat1 = start.lat/100000.;
|
|
||||||
double lon1 = start.lon/100000.;
|
|
||||||
|
|
||||||
double x1 = ( lon1 + 180.0 ) / 360.0;
|
|
||||||
double y1 = ( lat1 + 180.0 ) / 360.0;
|
|
||||||
|
|
||||||
double lat2 = target.lat/100000.;
|
|
||||||
double lon2 = target.lon/100000.;
|
|
||||||
|
|
||||||
double x2 = ( lon2 + 180.0 ) / 360.0;
|
|
||||||
double y2 = ( lat2 + 180.0 ) / 360.0;
|
|
||||||
|
|
||||||
Bresenham(x1*32768, y1*32768, x2*32768, y2*32768, indexList);
|
|
||||||
BOOST_FOREACH(BresenhamPixel & pixel, indexList) {
|
|
||||||
int fileIndex = (pixel.second-1)*32768 + pixel.first;
|
|
||||||
int ramIndex = GetRAMIndexFromFileIndex(fileIndex);
|
|
||||||
pixel.first = fileIndex;
|
|
||||||
pixel.second = ramIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetFileIndexForLatLon(const int lt, const int ln) {
|
|
||||||
double lat = lt/100000.;
|
|
||||||
double lon = ln/100000.;
|
|
||||||
|
|
||||||
double x = ( lon + 180.0 ) / 360.0;
|
|
||||||
double y = ( lat + 180.0 ) / 360.0;
|
|
||||||
|
|
||||||
if( x>1.0 || x < 0.)
|
|
||||||
return UINT_MAX;
|
|
||||||
if( y>1.0 || y < 0.)
|
|
||||||
return UINT_MAX;
|
|
||||||
|
|
||||||
unsigned line = (32768 * (32768-1))*y;
|
|
||||||
line = line - (line % 32768);
|
|
||||||
assert(line % 32768 == 0);
|
|
||||||
unsigned column = 32768.*x;
|
|
||||||
unsigned fileIndex = line+column;
|
|
||||||
return fileIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned GetRAMIndexFromFileIndex(const int fileIndex) const {
|
|
||||||
unsigned fileLine = fileIndex / 32768;
|
|
||||||
fileLine = fileLine / 32;
|
|
||||||
fileLine = fileLine * 1024;
|
|
||||||
unsigned fileColumn = (fileIndex % 32768);
|
|
||||||
fileColumn = fileColumn / 32;
|
|
||||||
unsigned ramIndex = fileLine + fileColumn;
|
|
||||||
assert(ramIndex < 1024*1024);
|
|
||||||
return ramIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
const static unsigned long END_OF_BUCKET_DELIMITER = UINT_MAX;
|
|
||||||
|
|
||||||
std::ofstream indexOutFile;
|
|
||||||
std::ifstream ramInFile;
|
|
||||||
#ifndef ROUTED
|
|
||||||
stxxl::vector<GridEntry> entries;
|
|
||||||
#endif
|
|
||||||
std::vector<unsigned long> ramIndexTable; //8 MB for first level index in RAM
|
|
||||||
std::string iif;
|
|
||||||
// LRUCache<int,std::vector<unsigned> > cellCache;
|
|
||||||
// LRUCache<int,std::vector<_Edge> > fileCache;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef NNGrid::NNGrid<false> ReadOnlyGrid;
|
|
||||||
typedef NNGrid::NNGrid<true > WritableGrid;
|
|
||||||
|
|
||||||
#endif /* NNGRID_H_ */
|
|
||||||
@@ -21,104 +21,184 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef NODEINFORMATIONHELPDESK_H_
|
#ifndef NODEINFORMATIONHELPDESK_H_
|
||||||
#define NODEINFORMATIONHELPDESK_H_
|
#define NODEINFORMATIONHELPDESK_H_
|
||||||
|
|
||||||
#include <fstream>
|
#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 <iostream>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "NNGrid.h"
|
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "NodeCoords.h"
|
|
||||||
|
|
||||||
class NodeInformationHelpDesk{
|
class NodeInformationHelpDesk : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc) : numberOfNodes(_numberOfNodes), checkSum(crc) {
|
NodeInformationHelpDesk(
|
||||||
readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
|
const std::string & ramIndexInput,
|
||||||
assert(0 == coordinateVector.size());
|
const std::string & fileIndexInput,
|
||||||
|
const std::string & nodes_filename,
|
||||||
|
const std::string & edges_filename,
|
||||||
|
const unsigned number_of_nodes,
|
||||||
|
const unsigned check_sum
|
||||||
|
) : number_of_nodes(number_of_nodes), check_sum(check_sum)
|
||||||
|
{
|
||||||
|
if ( ramIndexInput.empty() ) {
|
||||||
|
throw OSRMException("no ram index file name in server ini");
|
||||||
|
}
|
||||||
|
if ( fileIndexInput.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");
|
||||||
|
}
|
||||||
|
|
||||||
|
read_only_rtree = new StaticRTree<RTreeLeaf>(
|
||||||
|
ramIndexInput,
|
||||||
|
fileIndexInput
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == coordinateVector.size(),
|
||||||
|
"Coordinate vector not empty"
|
||||||
|
);
|
||||||
|
|
||||||
|
LoadNodesAndEdges(nodes_filename, edges_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Todo: Shared memory mechanism
|
//Todo: Shared memory mechanism
|
||||||
// NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned crc) : checkSum(crc) {
|
|
||||||
// readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
|
|
||||||
// }
|
|
||||||
|
|
||||||
~NodeInformationHelpDesk() {
|
~NodeInformationHelpDesk() {
|
||||||
delete readOnlyGrid;
|
delete read_only_rtree;
|
||||||
}
|
|
||||||
void initNNGrid(std::ifstream& nodesInstream, std::ifstream& edgesInStream) {
|
|
||||||
DEBUG("Loading node data");
|
|
||||||
NodeInfo b;
|
|
||||||
while(!nodesInstream.eof()) {
|
|
||||||
nodesInstream.read((char *)&b, sizeof(NodeInfo));
|
|
||||||
coordinateVector.push_back(_Coordinate(b.lat, b.lon));
|
|
||||||
}
|
|
||||||
std::vector<_Coordinate>(coordinateVector).swap(coordinateVector);
|
|
||||||
nodesInstream.close();
|
|
||||||
|
|
||||||
DEBUG("Loading edge data");
|
|
||||||
unsigned numberOfOrigEdges(0);
|
|
||||||
edgesInStream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
|
|
||||||
origEdgeData.resize(numberOfOrigEdges);
|
|
||||||
edgesInStream.read((char*)&(origEdgeData[0]), numberOfOrigEdges*sizeof(OriginalEdgeData));
|
|
||||||
edgesInStream.close();
|
|
||||||
DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
|
|
||||||
DEBUG("Opening NN indices");
|
|
||||||
readOnlyGrid->OpenIndexFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
void initNNGrid() {
|
|
||||||
readOnlyGrid->OpenIndexFiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int getLatitudeOfNode(const unsigned id) const {
|
inline int getLatitudeOfNode(const unsigned id) const {
|
||||||
const NodeID node = origEdgeData.at(id).viaNode;
|
const NodeID node = origEdgeData_viaNode.at(id);
|
||||||
return coordinateVector.at(node).lat;
|
return coordinateVector.at(node).lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int getLongitudeOfNode(const unsigned id) const {
|
inline int getLongitudeOfNode(const unsigned id) const {
|
||||||
const NodeID node = origEdgeData.at(id).viaNode;
|
const NodeID node = origEdgeData_viaNode.at(id);
|
||||||
return coordinateVector.at(node).lon;
|
return coordinateVector.at(node).lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
|
inline unsigned getNameIndexFromEdgeID(const unsigned id) const {
|
||||||
return origEdgeData.at(id).nameID;
|
return origEdgeData_nameID.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
|
inline TurnInstruction getTurnInstructionFromEdgeID(const unsigned id) const {
|
||||||
return origEdgeData.at(id).turnInstruction;
|
return origEdgeData_turnInstruction.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NodeID getNumberOfNodes() const { return numberOfNodes; }
|
inline NodeID getNumberOfNodes() const {
|
||||||
inline NodeID getNumberOfNodes2() const { return coordinateVector.size(); }
|
return number_of_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool FindNearestNodeCoordForLatLon(const _Coordinate& coord, _Coordinate& result) const {
|
inline NodeID getNumberOfNodes2() const {
|
||||||
return readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result);
|
return coordinateVector.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) const {
|
inline bool FindNearestNodeCoordForLatLon(
|
||||||
return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode, zoomLevel);
|
const FixedPointCoordinate& input_coordinate,
|
||||||
}
|
FixedPointCoordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const {
|
||||||
|
PhantomNode resulting_phantom_node;
|
||||||
|
bool foundNode = FindPhantomNodeForCoordinate(
|
||||||
|
input_coordinate,
|
||||||
|
resulting_phantom_node, zoom_level
|
||||||
|
);
|
||||||
|
result = resulting_phantom_node.location;
|
||||||
|
return foundNode;
|
||||||
|
}
|
||||||
|
|
||||||
inline void FindRoutingStarts(const _Coordinate &start, const _Coordinate &target, PhantomNodes & phantomNodes, const unsigned zoomLevel) const {
|
inline bool FindPhantomNodeForCoordinate(
|
||||||
readOnlyGrid->FindRoutingStarts(start, target, phantomNodes, zoomLevel);
|
const FixedPointCoordinate & input_coordinate,
|
||||||
}
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
inline void FindNearestPointOnEdge(const _Coordinate & input, _Coordinate& output){
|
) const {
|
||||||
readOnlyGrid->FindNearestPointOnEdge(input, output);
|
return read_only_rtree->FindPhantomNodeForCoordinate(
|
||||||
}
|
input_coordinate,
|
||||||
|
resulting_phantom_node,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned GetCheckSum() const {
|
inline unsigned GetCheckSum() const {
|
||||||
return checkSum;
|
return check_sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<_Coordinate> coordinateVector;
|
void LoadNodesAndEdges(
|
||||||
std::vector<OriginalEdgeData> origEdgeData;
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
ReadOnlyGrid * readOnlyGrid;
|
boost::filesystem::path edges_file(edges_filename);
|
||||||
const unsigned numberOfNodes;
|
if ( !boost::filesystem::exists( edges_file ) ) {
|
||||||
const unsigned checkSum;
|
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 b;
|
||||||
|
while(!nodes_input_stream.eof()) {
|
||||||
|
nodes_input_stream.read((char *)&b, sizeof(NodeInfo));
|
||||||
|
coordinateVector.push_back(FixedPointCoordinate(b.lat, b.lon));
|
||||||
|
}
|
||||||
|
std::vector<FixedPointCoordinate>(coordinateVector).swap(coordinateVector);
|
||||||
|
nodes_input_stream.close();
|
||||||
|
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Loading edge data";
|
||||||
|
unsigned numberOfOrigEdges(0);
|
||||||
|
edges_input_stream.read((char*)&numberOfOrigEdges, sizeof(unsigned));
|
||||||
|
origEdgeData_viaNode.resize(numberOfOrigEdges);
|
||||||
|
origEdgeData_nameID.resize(numberOfOrigEdges);
|
||||||
|
origEdgeData_turnInstruction.resize(numberOfOrigEdges);
|
||||||
|
|
||||||
|
OriginalEdgeData deserialized_originalEdgeData;
|
||||||
|
for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
|
||||||
|
edges_input_stream.read(
|
||||||
|
(char*)&(deserialized_originalEdgeData),
|
||||||
|
sizeof(OriginalEdgeData)
|
||||||
|
);
|
||||||
|
origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
|
||||||
|
origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID;
|
||||||
|
origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
|
||||||
|
}
|
||||||
|
edges_input_stream.close();
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Loaded " << numberOfOrigEdges << " orig edges";
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Opening NN indices";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FixedPointCoordinate> coordinateVector;
|
||||||
|
std::vector<NodeID> origEdgeData_viaNode;
|
||||||
|
std::vector<unsigned> origEdgeData_nameID;
|
||||||
|
std::vector<TurnInstruction> origEdgeData_turnInstruction;
|
||||||
|
|
||||||
|
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * read_only_rtree;
|
||||||
|
const unsigned number_of_nodes;
|
||||||
|
const unsigned check_sum;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*NODEINFORMATIONHELPDESK_H_*/
|
#endif /*NODEINFORMATIONHELPDESK_H_*/
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef PERCENT_H
|
#ifndef PERCENT_H
|
||||||
#define PERCENT_H
|
#define PERCENT_H
|
||||||
|
|
||||||
|
#include "../Util/OpenMPWrapper.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
class Percent
|
class Percent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -24,13 +24,20 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "Coordinate.h"
|
#include "Coordinate.h"
|
||||||
|
|
||||||
struct PhantomNode {
|
struct PhantomNode {
|
||||||
PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.) {}
|
PhantomNode() :
|
||||||
|
edgeBasedNode(UINT_MAX),
|
||||||
|
nodeBasedEdgeNameID(UINT_MAX),
|
||||||
|
weight1(INT_MAX),
|
||||||
|
weight2(INT_MAX),
|
||||||
|
ratio(0.)
|
||||||
|
{ }
|
||||||
|
|
||||||
NodeID edgeBasedNode;
|
NodeID edgeBasedNode;
|
||||||
unsigned nodeBasedEdgeNameID;
|
unsigned nodeBasedEdgeNameID;
|
||||||
int weight1;
|
int weight1;
|
||||||
int weight2;
|
int weight2;
|
||||||
double ratio;
|
double ratio;
|
||||||
_Coordinate location;
|
FixedPointCoordinate location;
|
||||||
void Reset() {
|
void Reset() {
|
||||||
edgeBasedNode = UINT_MAX;
|
edgeBasedNode = UINT_MAX;
|
||||||
nodeBasedEdgeNameID = UINT_MAX;
|
nodeBasedEdgeNameID = UINT_MAX;
|
||||||
@@ -88,7 +95,7 @@ inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){
|
|||||||
struct NodesOfEdge {
|
struct NodesOfEdge {
|
||||||
NodeID edgeBasedNode;
|
NodeID edgeBasedNode;
|
||||||
double ratio;
|
double ratio;
|
||||||
_Coordinate projectedPoint;
|
FixedPointCoordinate projectedPoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PHANTOMNODES_H_ */
|
#endif /* PHANTOMNODES_H_ */
|
||||||
|
|||||||
+11
-20
@@ -18,8 +18,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef QUERYEDGE_H_
|
#ifndef QUERYEDGE_H_
|
||||||
#define QUERYEDGE_H_
|
#define QUERYEDGE_H_
|
||||||
|
|
||||||
@@ -29,7 +27,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
struct OriginalEdgeData{
|
struct OriginalEdgeData{
|
||||||
explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {}
|
explicit OriginalEdgeData(
|
||||||
|
NodeID viaNode,
|
||||||
|
unsigned nameID,
|
||||||
|
TurnInstruction turnInstruction
|
||||||
|
) : viaNode(viaNode), nameID(nameID), turnInstruction(turnInstruction) {}
|
||||||
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
|
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
@@ -41,28 +43,17 @@ struct QueryEdge {
|
|||||||
NodeID target;
|
NodeID target;
|
||||||
struct EdgeData {
|
struct EdgeData {
|
||||||
NodeID id:31;
|
NodeID id:31;
|
||||||
int distance:30;
|
|
||||||
bool shortcut:1;
|
bool shortcut:1;
|
||||||
|
int distance:30;
|
||||||
bool forward:1;
|
bool forward:1;
|
||||||
bool backward:1;
|
bool backward:1;
|
||||||
} data;
|
} data;
|
||||||
bool operator<( const QueryEdge& right ) const {
|
|
||||||
if ( source != right.source )
|
|
||||||
return source < right.source;
|
|
||||||
return target < right.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
//sorts by source and other attributes
|
bool operator<( const QueryEdge& right ) const {
|
||||||
static bool CompareBySource( const QueryEdge& left, const QueryEdge& right ) {
|
if ( source != right.source ) {
|
||||||
if ( left.source != right.source )
|
return source < right.source;
|
||||||
return left.source < right.source;
|
}
|
||||||
int l = ( left.data.forward ? -1 : 0 ) + ( left.data.backward ? -1 : 0 );
|
return target < right.target;
|
||||||
int r = ( right.data.forward ? -1 : 0 ) + ( right.data.backward ? -1 : 0 );
|
|
||||||
if ( l != r )
|
|
||||||
return l < r;
|
|
||||||
if ( left.target != right.target )
|
|
||||||
return left.target < right.target;
|
|
||||||
return left.data.distance < right.data.distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator== ( const QueryEdge& right ) const {
|
bool operator== ( const QueryEdge& right ) const {
|
||||||
|
|||||||
@@ -21,32 +21,43 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef _NODE_COORDS_H
|
#ifndef _NODE_COORDS_H
|
||||||
#define _NODE_COORDS_H
|
#define _NODE_COORDS_H
|
||||||
|
|
||||||
#include <cassert>
|
#include "Coordinate.h"
|
||||||
#include <cstddef>
|
|
||||||
#include <climits>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
template<typename NodeT>
|
#include <boost/assert.hpp>
|
||||||
struct NodeCoords {
|
|
||||||
typedef unsigned key_type; //type of NodeID
|
#include <cstddef>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
struct NodeInfo {
|
||||||
|
typedef NodeID key_type; //type of NodeID
|
||||||
typedef int value_type; //type of lat,lons
|
typedef int value_type; //type of lat,lons
|
||||||
|
|
||||||
NodeCoords(int _lat, int _lon, NodeT _id) : lat(_lat), lon(_lon), id(_id) {}
|
NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {}
|
||||||
NodeCoords() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {}
|
||||||
int lat;
|
int lat;
|
||||||
int lon;
|
int lon;
|
||||||
NodeT id;
|
NodeID id;
|
||||||
|
|
||||||
static NodeCoords<NodeT> min_value() {
|
static NodeInfo min_value() {
|
||||||
return NodeCoords<NodeT>(-90*100000,-180*100000,std::numeric_limits<NodeT>::min());
|
return NodeInfo(
|
||||||
}
|
-90*COORDINATE_PRECISION,
|
||||||
static NodeCoords<NodeT> max_value() {
|
-180*COORDINATE_PRECISION,
|
||||||
return NodeCoords<NodeT>(90*100000, 180*100000, std::numeric_limits<NodeT>::max());
|
std::numeric_limits<NodeID>::min()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type operator[](std::size_t n) const {
|
static NodeInfo max_value() {
|
||||||
|
return NodeInfo(
|
||||||
|
90*COORDINATE_PRECISION,
|
||||||
|
180*COORDINATE_PRECISION,
|
||||||
|
std::numeric_limits<NodeID>::max()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type operator[](const std::size_t n) const {
|
||||||
switch(n) {
|
switch(n) {
|
||||||
case 1:
|
case 1:
|
||||||
return lat;
|
return lat;
|
||||||
@@ -55,15 +66,13 @@ struct NodeCoords {
|
|||||||
return lon;
|
return lon;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert(false);
|
BOOST_ASSERT_MSG(false, "should not happen");
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NodeCoords<NodeID> NodeInfo;
|
|
||||||
|
|
||||||
#endif //_NODE_COORDS_H
|
#endif //_NODE_COORDS_H
|
||||||
@@ -21,8 +21,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef RAWROUTEDATA_H_
|
#ifndef RAWROUTEDATA_H_
|
||||||
#define RAWROUTEDATA_H_
|
#define RAWROUTEDATA_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
struct _PathData {
|
struct _PathData {
|
||||||
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
||||||
NodeID node;
|
NodeID node;
|
||||||
@@ -35,7 +39,7 @@ struct RawRouteData {
|
|||||||
std::vector< _PathData > computedShortestPath;
|
std::vector< _PathData > computedShortestPath;
|
||||||
std::vector< _PathData > computedAlternativePath;
|
std::vector< _PathData > computedAlternativePath;
|
||||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
std::vector< PhantomNodes > segmentEndCoordinates;
|
||||||
std::vector< _Coordinate > rawViaNodeCoordinates;
|
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
|
||||||
unsigned checkSum;
|
unsigned checkSum;
|
||||||
int lengthOfShortestPath;
|
int lengthOfShortestPath;
|
||||||
int lengthOfAlternativePath;
|
int lengthOfAlternativePath;
|
||||||
@@ -23,40 +23,78 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef RESTRICTION_H_
|
#ifndef RESTRICTION_H_
|
||||||
#define RESTRICTION_H_
|
#define RESTRICTION_H_
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
struct _Restriction {
|
struct TurnRestriction {
|
||||||
NodeID viaNode;
|
NodeID viaNode;
|
||||||
NodeID fromNode;
|
NodeID fromNode;
|
||||||
NodeID toNode;
|
NodeID toNode;
|
||||||
struct Bits { //mostly unused
|
struct Bits { //mostly unused
|
||||||
Bits() : isOnly(false), unused1(false), unused2(false), unused3(false), unused4(false), unused5(false), unused6(false), unused7(false) {}
|
Bits()
|
||||||
char isOnly:1;
|
:
|
||||||
char unused1:1;
|
isOnly(false),
|
||||||
char unused2:1;
|
unused1(false),
|
||||||
char unused3:1;
|
unused2(false),
|
||||||
char unused4:1;
|
unused3(false),
|
||||||
char unused5:1;
|
unused4(false),
|
||||||
char unused6:1;
|
unused5(false),
|
||||||
char unused7:1;
|
unused6(false),
|
||||||
|
unused7(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool isOnly:1;
|
||||||
|
bool unused1:1;
|
||||||
|
bool unused2:1;
|
||||||
|
bool unused3:1;
|
||||||
|
bool unused4:1;
|
||||||
|
bool unused5:1;
|
||||||
|
bool unused6:1;
|
||||||
|
bool unused7:1;
|
||||||
} flags;
|
} flags;
|
||||||
|
|
||||||
_Restriction(NodeID vn) : viaNode(vn), fromNode(UINT_MAX), toNode(UINT_MAX) { }
|
TurnRestriction(NodeID viaNode) :
|
||||||
_Restriction(bool isOnly = false) : viaNode(UINT_MAX), fromNode(UINT_MAX), toNode(UINT_MAX) {
|
viaNode(viaNode),
|
||||||
|
fromNode(UINT_MAX),
|
||||||
|
toNode(UINT_MAX) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TurnRestriction(const bool isOnly = false) :
|
||||||
|
viaNode(UINT_MAX),
|
||||||
|
fromNode(UINT_MAX),
|
||||||
|
toNode(UINT_MAX) {
|
||||||
flags.isOnly = isOnly;
|
flags.isOnly = isOnly;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool CmpRestrictionByFrom ( _Restriction a, _Restriction b) { return (a.fromNode < b.fromNode); }
|
|
||||||
|
|
||||||
struct _RawRestrictionContainer {
|
struct _RawRestrictionContainer {
|
||||||
_Restriction restriction;
|
TurnRestriction restriction;
|
||||||
EdgeID fromWay;
|
EdgeID fromWay;
|
||||||
EdgeID toWay;
|
EdgeID toWay;
|
||||||
unsigned viaNode;
|
unsigned viaNode;
|
||||||
|
|
||||||
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaNode(vw) { restriction.viaNode = vn;}
|
_RawRestrictionContainer(
|
||||||
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaNode(UINT_MAX) { restriction.flags.isOnly = isOnly;}
|
EdgeID fromWay,
|
||||||
|
EdgeID toWay,
|
||||||
|
NodeID vn,
|
||||||
|
unsigned vw
|
||||||
|
) :
|
||||||
|
fromWay(fromWay),
|
||||||
|
toWay(toWay),
|
||||||
|
viaNode(vw)
|
||||||
|
{
|
||||||
|
restriction.viaNode = vn;
|
||||||
|
}
|
||||||
|
_RawRestrictionContainer(
|
||||||
|
bool isOnly = false
|
||||||
|
) :
|
||||||
|
fromWay(UINT_MAX),
|
||||||
|
toWay(UINT_MAX),
|
||||||
|
viaNode(UINT_MAX)
|
||||||
|
{
|
||||||
|
restriction.flags.isOnly = isOnly;
|
||||||
|
}
|
||||||
|
|
||||||
static _RawRestrictionContainer min_value() {
|
static _RawRestrictionContainer min_value() {
|
||||||
return _RawRestrictionContainer(0, 0, 0, 0);
|
return _RawRestrictionContainer(0, 0, 0, 0);
|
||||||
@@ -66,7 +104,7 @@ struct _RawRestrictionContainer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpRestrictionContainerByFrom: public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
struct CmpRestrictionContainerByFrom : public std::binary_function<_RawRestrictionContainer, _RawRestrictionContainer, bool> {
|
||||||
typedef _RawRestrictionContainer value_type;
|
typedef _RawRestrictionContainer value_type;
|
||||||
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
bool operator () (const _RawRestrictionContainer & a, const _RawRestrictionContainer & b) const {
|
||||||
return a.fromWay < b.fromWay;
|
return a.fromWay < b.fromWay;
|
||||||
@@ -92,6 +130,4 @@ struct CmpRestrictionContainerByTo: public std::binary_function<_RawRestrictionC
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* RESTRICTION_H_ */
|
#endif /* RESTRICTION_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SearchEngine.h"
|
||||||
|
|
||||||
|
SearchEngine::SearchEngine(
|
||||||
|
QueryGraph * g,
|
||||||
|
NodeInformationHelpDesk * nh,
|
||||||
|
std::vector<std::string> & n
|
||||||
|
) :
|
||||||
|
_queryData(g, nh, n),
|
||||||
|
shortestPath(_queryData),
|
||||||
|
alternativePaths(_queryData)
|
||||||
|
{}
|
||||||
|
SearchEngine::~SearchEngine() {}
|
||||||
|
|
||||||
|
void SearchEngine::GetCoordinatesForNodeID(
|
||||||
|
NodeID id,
|
||||||
|
FixedPointCoordinate& result
|
||||||
|
) const {
|
||||||
|
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
|
||||||
|
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(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 {
|
||||||
|
bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0);
|
||||||
|
if (is_name_invalid) {
|
||||||
|
return std::string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTMLEntitize(_queryData.names.at(nameID));
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||||
|
SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
||||||
|
|
||||||
|
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
||||||
|
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
||||||
|
|
||||||
|
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||||
|
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||||
|
|
||||||
+24
-127
@@ -21,151 +21,48 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef SEARCHENGINE_H_
|
#ifndef SEARCHENGINE_H_
|
||||||
#define SEARCHENGINE_H_
|
#define SEARCHENGINE_H_
|
||||||
|
|
||||||
#include <climits>
|
#include "Coordinate.h"
|
||||||
#include <deque>
|
|
||||||
#include "SimpleStack.h"
|
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#include "BinaryHeap.h"
|
|
||||||
#include "NodeInformationHelpDesk.h"
|
#include "NodeInformationHelpDesk.h"
|
||||||
#include "PhantomNodes.h"
|
#include "PhantomNodes.h"
|
||||||
|
#include "QueryEdge.h"
|
||||||
|
#include "SearchEngineData.h"
|
||||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||||
#include "../RoutingAlgorithms/BasicRoutingInterface.h"
|
|
||||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct _HeapData {
|
#include <climits>
|
||||||
NodeID parent;
|
#include <string>
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
#include <vector>
|
||||||
};
|
|
||||||
|
|
||||||
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > > SearchEngineHeapPtr;
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT>
|
|
||||||
struct SearchEngineData {
|
|
||||||
typedef SearchEngineHeapPtr HeapPtr;
|
|
||||||
typedef GraphT Graph;
|
|
||||||
SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
|
|
||||||
const GraphT * graph;
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
|
||||||
std::vector<string> & names;
|
|
||||||
static HeapPtr forwardHeap;
|
|
||||||
static HeapPtr backwardHeap;
|
|
||||||
static HeapPtr forwardHeap2;
|
|
||||||
static HeapPtr backwardHeap2;
|
|
||||||
static HeapPtr forwardHeap3;
|
|
||||||
static HeapPtr backwardHeap3;
|
|
||||||
|
|
||||||
inline void InitializeOrClearFirstThreadLocalStorage() {
|
|
||||||
if(!forwardHeap.get()) {
|
|
||||||
forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
forwardHeap->Clear();
|
|
||||||
|
|
||||||
if(!backwardHeap.get()) {
|
|
||||||
backwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backwardHeap->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InitializeOrClearSecondThreadLocalStorage() {
|
|
||||||
if(!forwardHeap2.get()) {
|
|
||||||
forwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
forwardHeap2->Clear();
|
|
||||||
|
|
||||||
if(!backwardHeap2.get()) {
|
|
||||||
backwardHeap2.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backwardHeap2->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InitializeOrClearThirdThreadLocalStorage() {
|
|
||||||
if(!forwardHeap3.get()) {
|
|
||||||
forwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
forwardHeap3->Clear();
|
|
||||||
|
|
||||||
if(!backwardHeap3.get()) {
|
|
||||||
backwardHeap3.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> >(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backwardHeap3->Clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT>
|
|
||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
private:
|
private:
|
||||||
typedef SearchEngineData<EdgeData, GraphT> SearchEngineDataT;
|
SearchEngineData _queryData;
|
||||||
SearchEngineDataT _queryData;
|
|
||||||
|
|
||||||
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
|
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting<SearchEngineDataT> shortestPath;
|
ShortestPathRouting<SearchEngineData> shortestPath;
|
||||||
AlternativeRouting<SearchEngineDataT> alternativePaths;
|
AlternativeRouting<SearchEngineData> alternativePaths;
|
||||||
|
|
||||||
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<string> & n) :
|
SearchEngine(
|
||||||
_queryData(g, nh, n),
|
QueryGraph * g,
|
||||||
shortestPath(_queryData),
|
NodeInformationHelpDesk * nh,
|
||||||
alternativePaths(_queryData)
|
std::vector<std::string> & n
|
||||||
{}
|
);
|
||||||
~SearchEngine() {}
|
~SearchEngine();
|
||||||
|
|
||||||
inline void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
|
void GetCoordinatesForNodeID(NodeID id, FixedPointCoordinate& result) const;
|
||||||
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
|
|
||||||
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
|
void FindPhantomNodeForCoordinate(
|
||||||
_queryData.nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
|
const FixedPointCoordinate & location,
|
||||||
}
|
PhantomNode & result,
|
||||||
|
unsigned zoomLevel
|
||||||
|
) const;
|
||||||
|
|
||||||
inline void FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result, unsigned zoomLevel) const {
|
NodeID GetNameIDForOriginDestinationNodeID(
|
||||||
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(location, result, zoomLevel);
|
const NodeID s, const NodeID t) const;
|
||||||
}
|
|
||||||
|
|
||||||
inline NodeID 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 EdgeData ed = _queryData.graph->GetEdgeData(e);
|
|
||||||
return ed.via;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string GetEscapedNameForNameID(const unsigned nameID) const {
|
|
||||||
return ((nameID >= _queryData.names.size() || nameID == 0) ? std::string("") : HTMLEntitize(_queryData.names.at(nameID)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
|
|
||||||
const unsigned nameID = _queryData.graph->GetEdgeData(edgeID).nameID1;
|
|
||||||
return GetEscapedNameForNameID(nameID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string GetEscapedNameForNameID(const unsigned nameID) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap;
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap;
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap2;
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap2;
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap3;
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap3;
|
|
||||||
|
|
||||||
#endif /* SEARCHENGINE_H_ */
|
#endif /* SEARCHENGINE_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
|
||||||
|
if(!forwardHeap.get()) {
|
||||||
|
forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
forwardHeap->Clear();
|
||||||
|
}
|
||||||
|
if(!backwardHeap.get()) {
|
||||||
|
backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
backwardHeap->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
|
||||||
|
if(!forwardHeap2.get()) {
|
||||||
|
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
forwardHeap2->Clear();
|
||||||
|
}
|
||||||
|
if(!backwardHeap2.get()) {
|
||||||
|
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
backwardHeap2->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
|
||||||
|
if(!forwardHeap3.get()) {
|
||||||
|
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
forwardHeap3->Clear();
|
||||||
|
}
|
||||||
|
if(!backwardHeap3.get()) {
|
||||||
|
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
backwardHeap3->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BinaryHeap.h"
|
||||||
|
#include "QueryEdge.h"
|
||||||
|
#include "NodeInformationHelpDesk.h"
|
||||||
|
#include "StaticGraph.h"
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct _HeapData {
|
||||||
|
NodeID parent;
|
||||||
|
_HeapData( NodeID p ) : parent(p) { }
|
||||||
|
};
|
||||||
|
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
|
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
|
||||||
|
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
|
||||||
|
|
||||||
|
struct SearchEngineData {
|
||||||
|
typedef QueryGraph Graph;
|
||||||
|
typedef QueryHeapType QueryHeap;
|
||||||
|
SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
|
||||||
|
const QueryGraph * graph;
|
||||||
|
NodeInformationHelpDesk * nodeHelpDesk;
|
||||||
|
std::vector<std::string> & names;
|
||||||
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
|
static SearchEngineHeapPtr backwardHeap;
|
||||||
|
static SearchEngineHeapPtr forwardHeap2;
|
||||||
|
static SearchEngineHeapPtr backwardHeap2;
|
||||||
|
static SearchEngineHeapPtr forwardHeap3;
|
||||||
|
static SearchEngineHeapPtr backwardHeap3;
|
||||||
|
|
||||||
|
void InitializeOrClearFirstThreadLocalStorage();
|
||||||
|
|
||||||
|
void InitializeOrClearSecondThreadLocalStorage();
|
||||||
|
|
||||||
|
void InitializeOrClearThirdThreadLocalStorage();
|
||||||
|
};
|
||||||
@@ -21,21 +21,22 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef SEGMENTINFORMATION_H_
|
#ifndef SEGMENTINFORMATION_H_
|
||||||
#define SEGMENTINFORMATION_H_
|
#define SEGMENTINFORMATION_H_
|
||||||
|
|
||||||
|
#include "TurnInstructions.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "TurnInstructions.h"
|
|
||||||
|
|
||||||
struct SegmentInformation {
|
struct SegmentInformation {
|
||||||
_Coordinate location;
|
FixedPointCoordinate location;
|
||||||
NodeID nameID;
|
NodeID nameID;
|
||||||
double length;
|
double length;
|
||||||
unsigned duration;
|
unsigned duration;
|
||||||
double bearing;
|
double bearing;
|
||||||
TurnInstruction turnInstruction;
|
TurnInstruction turnInstruction;
|
||||||
bool necessary;
|
bool necessary;
|
||||||
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
|
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) :
|
||||||
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
|
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {}
|
||||||
SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
|
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) :
|
||||||
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
|
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef STATICGRAPH_H_INCLUDED
|
#ifndef STATICGRAPH_H_INCLUDED
|
||||||
#define STATICGRAPH_H_INCLUDED
|
#define STATICGRAPH_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include "../Util/SimpleLogger.h"
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "ImportEdge.h"
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
template< typename EdgeDataT>
|
||||||
class StaticGraph {
|
class StaticGraph {
|
||||||
@@ -100,12 +100,17 @@ public:
|
|||||||
if(data.shortcut) {
|
if(data.shortcut) {
|
||||||
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
|
unsigned eid2 = FindEdgeInEitherDirection(u, data.id);
|
||||||
if(eid2 == UINT_MAX) {
|
if(eid2 == UINT_MAX) {
|
||||||
DEBUG("cannot find first segment of edge (" << u << "," << data.id << "," << v << ")");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"cannot find first segment of edge (" <<
|
||||||
|
u << "," << data.id << "," << v << ")";
|
||||||
|
|
||||||
data.shortcut = false;
|
data.shortcut = false;
|
||||||
}
|
}
|
||||||
eid2 = FindEdgeInEitherDirection(data.id, v);
|
eid2 = FindEdgeInEitherDirection(data.id, v);
|
||||||
if(eid2 == UINT_MAX) {
|
if(eid2 == UINT_MAX) {
|
||||||
DEBUG("cannot find second segment of edge (" << u << "," << data.id << "," << v << ")");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"cannot find second segment of edge (" <<
|
||||||
|
u << "," << data.id << "," << v << ")";
|
||||||
data.shortcut = false;
|
data.shortcut = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,832 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STATICRTREE_H_
|
||||||
|
#define STATICRTREE_H_
|
||||||
|
|
||||||
|
#include "MercatorUtil.h"
|
||||||
|
#include "Coordinate.h"
|
||||||
|
#include "PhantomNodes.h"
|
||||||
|
#include "DeallocatingVector.h"
|
||||||
|
#include "HilbertValue.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/algorithm/minmax.hpp>
|
||||||
|
#include <boost/algorithm/minmax_element.hpp>
|
||||||
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cfloat>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
//tuning parameters
|
||||||
|
const static uint32_t RTREE_BRANCHING_FACTOR = 50;
|
||||||
|
const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
|
||||||
|
|
||||||
|
// Implements a static, i.e. packed, R-tree
|
||||||
|
|
||||||
|
static boost::thread_specific_ptr<boost::filesystem::ifstream> thread_local_rtree_stream;
|
||||||
|
|
||||||
|
template<class DataT>
|
||||||
|
class StaticRTree : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
struct RectangleInt2D {
|
||||||
|
RectangleInt2D() :
|
||||||
|
min_lon(INT_MAX),
|
||||||
|
max_lon(INT_MIN),
|
||||||
|
min_lat(INT_MAX),
|
||||||
|
max_lat(INT_MIN) {}
|
||||||
|
|
||||||
|
int32_t min_lon, max_lon;
|
||||||
|
int32_t min_lat, max_lat;
|
||||||
|
|
||||||
|
inline void InitializeMBRectangle(
|
||||||
|
const DataT * objects,
|
||||||
|
const uint32_t element_count
|
||||||
|
) {
|
||||||
|
for(uint32_t i = 0; i < element_count; ++i) {
|
||||||
|
min_lon = std::min(
|
||||||
|
min_lon, std::min(objects[i].lon1, objects[i].lon2)
|
||||||
|
);
|
||||||
|
max_lon = std::max(
|
||||||
|
max_lon, std::max(objects[i].lon1, objects[i].lon2)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_lat = std::min(
|
||||||
|
min_lat, std::min(objects[i].lat1, objects[i].lat2)
|
||||||
|
);
|
||||||
|
max_lat = std::max(
|
||||||
|
max_lat, std::max(objects[i].lat1, objects[i].lat2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AugmentMBRectangle(const RectangleInt2D & other) {
|
||||||
|
min_lon = std::min(min_lon, other.min_lon);
|
||||||
|
max_lon = std::max(max_lon, other.max_lon);
|
||||||
|
min_lat = std::min(min_lat, other.min_lat);
|
||||||
|
max_lat = std::max(max_lat, other.max_lat);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FixedPointCoordinate Centroid() const {
|
||||||
|
FixedPointCoordinate centroid;
|
||||||
|
//The coordinates of the midpoints are given by:
|
||||||
|
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
|
centroid.lon = (min_lon + max_lon)/2;
|
||||||
|
centroid.lat = (min_lat + max_lat)/2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Intersects(const RectangleInt2D & other) const {
|
||||||
|
FixedPointCoordinate upper_left (other.max_lat, other.min_lon);
|
||||||
|
FixedPointCoordinate upper_right(other.max_lat, other.max_lon);
|
||||||
|
FixedPointCoordinate lower_right(other.min_lat, other.max_lon);
|
||||||
|
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
|
||||||
|
|
||||||
|
return (
|
||||||
|
Contains(upper_left)
|
||||||
|
|| Contains(upper_right)
|
||||||
|
|| Contains(lower_right)
|
||||||
|
|| Contains(lower_left)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetMinDist(const FixedPointCoordinate & location) const {
|
||||||
|
bool is_contained = Contains(location);
|
||||||
|
if (is_contained) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
max_lat,
|
||||||
|
min_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
max_lat,
|
||||||
|
max_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
min_lat,
|
||||||
|
max_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
min_lat,
|
||||||
|
min_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return min_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetMinMaxDist(const FixedPointCoordinate & location) const {
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
//Get minmax distance to each of the four sides
|
||||||
|
FixedPointCoordinate upper_left (max_lat, min_lon);
|
||||||
|
FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||||
|
FixedPointCoordinate lower_right(min_lat, max_lon);
|
||||||
|
FixedPointCoordinate lower_left (min_lat, min_lon);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, upper_left ),
|
||||||
|
ApproximateDistance(location, upper_right)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, upper_right),
|
||||||
|
ApproximateDistance(location, lower_right)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, lower_right),
|
||||||
|
ApproximateDistance(location, lower_left )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, lower_left ),
|
||||||
|
ApproximateDistance(location, upper_left )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return min_max_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Contains(const FixedPointCoordinate & location) const {
|
||||||
|
bool lats_contained =
|
||||||
|
(location.lat > min_lat) && (location.lat < max_lat);
|
||||||
|
bool lons_contained =
|
||||||
|
(location.lon > min_lon) && (location.lon < max_lon);
|
||||||
|
return lats_contained && lons_contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline friend std::ostream & operator<< (
|
||||||
|
std::ostream & out,
|
||||||
|
const RectangleInt2D & rect
|
||||||
|
) {
|
||||||
|
out << rect.min_lat/COORDINATE_PRECISION << ","
|
||||||
|
<< rect.min_lon/COORDINATE_PRECISION << " "
|
||||||
|
<< rect.max_lat/COORDINATE_PRECISION << ","
|
||||||
|
<< rect.max_lon/COORDINATE_PRECISION;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef RectangleInt2D RectangleT;
|
||||||
|
|
||||||
|
struct WrappedInputElement {
|
||||||
|
explicit WrappedInputElement(
|
||||||
|
const uint32_t _array_index,
|
||||||
|
const uint64_t _hilbert_value
|
||||||
|
) : m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
|
||||||
|
|
||||||
|
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
|
||||||
|
|
||||||
|
uint32_t m_array_index;
|
||||||
|
uint64_t m_hilbert_value;
|
||||||
|
|
||||||
|
inline bool operator<(const WrappedInputElement & other) const {
|
||||||
|
return m_hilbert_value < other.m_hilbert_value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LeafNode {
|
||||||
|
LeafNode() : object_count(0) {}
|
||||||
|
uint32_t object_count;
|
||||||
|
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 {
|
||||||
|
explicit QueryCandidate(
|
||||||
|
const uint32_t n_id,
|
||||||
|
const double dist
|
||||||
|
) : node_id(n_id), min_dist(dist) {}
|
||||||
|
QueryCandidate() : node_id(UINT_MAX), min_dist(DBL_MAX) {}
|
||||||
|
uint32_t node_id;
|
||||||
|
double min_dist;
|
||||||
|
inline bool operator<(const QueryCandidate & other) const {
|
||||||
|
return min_dist < other.min_dist;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<TreeNode> m_search_tree;
|
||||||
|
uint64_t m_element_count;
|
||||||
|
|
||||||
|
const std::string m_leaf_node_filename;
|
||||||
|
public:
|
||||||
|
//Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1]
|
||||||
|
explicit StaticRTree(
|
||||||
|
std::vector<DataT> & input_data_vector,
|
||||||
|
const std::string tree_node_filename,
|
||||||
|
const std::string leaf_node_filename
|
||||||
|
)
|
||||||
|
: m_element_count(input_data_vector.size()),
|
||||||
|
m_leaf_node_filename(leaf_node_filename)
|
||||||
|
{
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
"constructing r-tree of " << m_element_count <<
|
||||||
|
" elements";
|
||||||
|
|
||||||
|
double time1 = get_timestamp();
|
||||||
|
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||||
|
|
||||||
|
//generate auxiliary vector of hilbert-values
|
||||||
|
#pragma omp parallel for schedule(guided)
|
||||||
|
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
||||||
|
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||||
|
//Get Hilbert-Value for centroid in mercartor projection
|
||||||
|
DataT & current_element = input_data_vector[element_counter];
|
||||||
|
FixedPointCoordinate current_centroid = current_element.Centroid();
|
||||||
|
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
|
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
|
||||||
|
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
|
||||||
|
|
||||||
|
}
|
||||||
|
//open leaf file
|
||||||
|
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
||||||
|
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
|
||||||
|
|
||||||
|
//sort the hilbert-value representatives
|
||||||
|
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
||||||
|
std::vector<TreeNode> tree_nodes_in_level;
|
||||||
|
|
||||||
|
//pack M elements into leaf node and write to leaf file
|
||||||
|
uint64_t processed_objects_count = 0;
|
||||||
|
while(processed_objects_count < m_element_count) {
|
||||||
|
|
||||||
|
LeafNode current_leaf;
|
||||||
|
TreeNode current_node;
|
||||||
|
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
|
||||||
|
if(m_element_count > (processed_objects_count + current_element_index)) {
|
||||||
|
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
|
||||||
|
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
|
||||||
|
++current_leaf.object_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate tree node that resemble the objects in leaf and store it for next level
|
||||||
|
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
||||||
|
current_node.child_is_on_disk = true;
|
||||||
|
current_node.children[0] = tree_nodes_in_level.size();
|
||||||
|
tree_nodes_in_level.push_back(current_node);
|
||||||
|
|
||||||
|
//write leaf_node to leaf node file
|
||||||
|
leaf_node_file.write((char*)¤t_leaf, sizeof(current_leaf));
|
||||||
|
processed_objects_count += current_leaf.object_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
//close leaf file
|
||||||
|
leaf_node_file.close();
|
||||||
|
|
||||||
|
uint32_t processing_level = 0;
|
||||||
|
while(1 < tree_nodes_in_level.size()) {
|
||||||
|
std::vector<TreeNode> tree_nodes_in_next_level;
|
||||||
|
uint32_t processed_tree_nodes_in_level = 0;
|
||||||
|
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
||||||
|
TreeNode parent_node;
|
||||||
|
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
|
||||||
|
for(
|
||||||
|
uint32_t current_child_node_index = 0;
|
||||||
|
RTREE_BRANCHING_FACTOR > current_child_node_index;
|
||||||
|
++current_child_node_index
|
||||||
|
) {
|
||||||
|
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
||||||
|
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
|
||||||
|
//add tree node to parent entry
|
||||||
|
parent_node.children[current_child_node_index] = m_search_tree.size();
|
||||||
|
m_search_tree.push_back(current_child_node);
|
||||||
|
//augment MBR of parent
|
||||||
|
parent_node.minimum_bounding_rectangle.AugmentMBRectangle(current_child_node.minimum_bounding_rectangle);
|
||||||
|
//increase counters
|
||||||
|
++parent_node.child_count;
|
||||||
|
++processed_tree_nodes_in_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree_nodes_in_next_level.push_back(parent_node);
|
||||||
|
}
|
||||||
|
tree_nodes_in_level.swap(tree_nodes_in_next_level);
|
||||||
|
++processing_level;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
|
||||||
|
//last remaining entry is the root node, store it
|
||||||
|
m_search_tree.push_back(tree_nodes_in_level[0]);
|
||||||
|
|
||||||
|
//reverse and renumber tree to have root at index 0
|
||||||
|
std::reverse(m_search_tree.begin(), m_search_tree.end());
|
||||||
|
#pragma omp parallel for schedule(guided)
|
||||||
|
for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
|
||||||
|
TreeNode & current_tree_node = m_search_tree[i];
|
||||||
|
for(uint32_t j = 0; j < current_tree_node.child_count; ++j) {
|
||||||
|
const uint32_t old_id = current_tree_node.children[j];
|
||||||
|
const uint32_t new_id = m_search_tree.size() - old_id - 1;
|
||||||
|
current_tree_node.children[j] = new_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//open tree file
|
||||||
|
boost::filesystem::ofstream tree_node_file(
|
||||||
|
tree_node_filename,
|
||||||
|
std::ios::binary
|
||||||
|
);
|
||||||
|
|
||||||
|
uint32_t size_of_tree = m_search_tree.size();
|
||||||
|
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||||
|
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
|
||||||
|
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode)*size_of_tree);
|
||||||
|
//close tree node file.
|
||||||
|
tree_node_file.close();
|
||||||
|
double time2 = get_timestamp();
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
"finished r-tree construction in " << (time2-time1) << " seconds";
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read-only operation for queries
|
||||||
|
explicit StaticRTree(
|
||||||
|
const std::string & node_filename,
|
||||||
|
const std::string & leaf_filename
|
||||||
|
) : m_leaf_node_filename(leaf_filename) {
|
||||||
|
//open tree node file and load into RAM.
|
||||||
|
boost::filesystem::path node_file(node_filename);
|
||||||
|
|
||||||
|
if ( !boost::filesystem::exists( node_file ) ) {
|
||||||
|
throw OSRMException("ram index file does not exist");
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( node_file ) ) {
|
||||||
|
throw OSRMException("ram index file is empty");
|
||||||
|
}
|
||||||
|
boost::filesystem::ifstream tree_node_file( node_file, std::ios::binary );
|
||||||
|
|
||||||
|
uint32_t tree_size = 0;
|
||||||
|
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
|
||||||
|
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
|
||||||
|
m_search_tree.resize(tree_size);
|
||||||
|
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
||||||
|
tree_node_file.close();
|
||||||
|
|
||||||
|
//open leaf node file and store thread specific pointer
|
||||||
|
boost::filesystem::path leaf_file(leaf_filename);
|
||||||
|
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();
|
||||||
|
|
||||||
|
//SimpleLogger().Write() << tree_size << " nodes in search tree";
|
||||||
|
//SimpleLogger().Write() << m_element_count << " elements in leafs";
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
inline void FindKNearestPhantomNodesForCoordinate(
|
||||||
|
const FixedPointCoordinate & location,
|
||||||
|
const unsigned zoom_level,
|
||||||
|
const unsigned candidate_count,
|
||||||
|
std::vector<std::pair<PhantomNode, double> > & result_vector
|
||||||
|
) const {
|
||||||
|
|
||||||
|
bool ignore_tiny_components = (zoom_level <= 14);
|
||||||
|
DataT nearest_edge;
|
||||||
|
|
||||||
|
uint32_t io_count = 0;
|
||||||
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
|
SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
|
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||||
|
|
||||||
|
//initialize queue with root element
|
||||||
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
|
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||||
|
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||||
|
|
||||||
|
while(!traversal_queue.empty()) {
|
||||||
|
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||||
|
|
||||||
|
++explored_tree_nodes_count;
|
||||||
|
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||||
|
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||||
|
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||||
|
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||||
|
if (current_tree_node.child_is_on_disk) {
|
||||||
|
LeafNode current_leaf_node;
|
||||||
|
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||||
|
++io_count;
|
||||||
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
|
DataT & current_edge = current_leaf_node.objects[i];
|
||||||
|
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double current_ratio = 0.;
|
||||||
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
|
input_coordinate,
|
||||||
|
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||||
|
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||||
|
nearest,
|
||||||
|
¤t_ratio
|
||||||
|
);
|
||||||
|
|
||||||
|
if(
|
||||||
|
current_perpendicular_distance < min_dist
|
||||||
|
&& !DoubleEpsilonCompare(
|
||||||
|
current_perpendicular_distance,
|
||||||
|
min_dist
|
||||||
|
)
|
||||||
|
) { //found a new minimum
|
||||||
|
min_dist = current_perpendicular_distance;
|
||||||
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
|
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||||
|
result_phantom_node.weight1 = current_edge.weight;
|
||||||
|
result_phantom_node.weight2 = INT_MAX;
|
||||||
|
result_phantom_node.location = nearest;
|
||||||
|
current_start_coordinate.lat = current_edge.lat1;
|
||||||
|
current_start_coordinate.lon = current_edge.lon1;
|
||||||
|
current_end_coordinate.lat = current_edge.lat2;
|
||||||
|
current_end_coordinate.lon = current_edge.lon2;
|
||||||
|
nearest_edge = current_edge;
|
||||||
|
found_a_nearest_edge = true;
|
||||||
|
} else if(
|
||||||
|
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||||
|
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||||
|
&& CoordinatesAreEquivalent(
|
||||||
|
current_start_coordinate,
|
||||||
|
FixedPointCoordinate(
|
||||||
|
current_edge.lat1,
|
||||||
|
current_edge.lon1
|
||||||
|
),
|
||||||
|
FixedPointCoordinate(
|
||||||
|
current_edge.lat2,
|
||||||
|
current_edge.lon2
|
||||||
|
),
|
||||||
|
current_end_coordinate
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
|
||||||
|
result_phantom_node.weight2 = current_edge.weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//traverse children, prune if global mindist is smaller than local one
|
||||||
|
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||||
|
const int32_t child_id = current_tree_node.children[i];
|
||||||
|
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||||
|
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||||
|
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||||
|
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||||
|
if( current_min_max_dist < min_max_dist ) {
|
||||||
|
min_max_dist = current_min_max_dist;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_max_dist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_dist) { //upward pruning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double distance_to_edge =
|
||||||
|
ApproximateDistance (
|
||||||
|
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||||
|
result_phantom_node.location
|
||||||
|
);
|
||||||
|
|
||||||
|
const double length_of_edge =
|
||||||
|
ApproximateDistance(
|
||||||
|
FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||||
|
FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2)
|
||||||
|
);
|
||||||
|
|
||||||
|
const double ratio = (found_a_nearest_edge ?
|
||||||
|
std::min(1., distance_to_edge/ length_of_edge ) : 0 );
|
||||||
|
result_phantom_node.weight1 *= ratio;
|
||||||
|
if(INT_MAX != result_phantom_node.weight2) {
|
||||||
|
result_phantom_node.weight2 *= (1.-ratio);
|
||||||
|
}
|
||||||
|
result_phantom_node.ratio = ratio;
|
||||||
|
|
||||||
|
//Hack to fix rounding errors and wandering via nodes.
|
||||||
|
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||||
|
result_phantom_node.location.lon = input_coordinate.lon;
|
||||||
|
}
|
||||||
|
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||||
|
result_phantom_node.location.lat = input_coordinate.lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no");
|
||||||
|
return found_a_nearest_edge;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
bool FindPhantomNodeForCoordinate(
|
||||||
|
const FixedPointCoordinate & input_coordinate,
|
||||||
|
PhantomNode & result_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) {
|
||||||
|
|
||||||
|
bool ignore_tiny_components = (zoom_level <= 14);
|
||||||
|
DataT nearest_edge;
|
||||||
|
|
||||||
|
uint32_t io_count = 0;
|
||||||
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
|
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
|
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||||
|
|
||||||
|
//initialize queue with root element
|
||||||
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
|
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||||
|
traversal_queue.push(
|
||||||
|
QueryCandidate(0, current_min_dist)
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
FLT_EPSILON > (0. - traversal_queue.top().min_dist),
|
||||||
|
"Root element in NN Search has min dist != 0."
|
||||||
|
);
|
||||||
|
|
||||||
|
while(!traversal_queue.empty()) {
|
||||||
|
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||||
|
|
||||||
|
++explored_tree_nodes_count;
|
||||||
|
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||||
|
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||||
|
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||||
|
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||||
|
if (current_tree_node.child_is_on_disk) {
|
||||||
|
LeafNode current_leaf_node;
|
||||||
|
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||||
|
++io_count;
|
||||||
|
//SimpleLogger().Write() << "checking " << current_leaf_node.object_count << " elements";
|
||||||
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
|
DataT & current_edge = current_leaf_node.objects[i];
|
||||||
|
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(current_edge.isIgnored()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double current_ratio = 0.;
|
||||||
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
|
input_coordinate,
|
||||||
|
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||||
|
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||||
|
nearest,
|
||||||
|
¤t_ratio
|
||||||
|
);
|
||||||
|
|
||||||
|
if(
|
||||||
|
current_perpendicular_distance < min_dist
|
||||||
|
&& !DoubleEpsilonCompare(
|
||||||
|
current_perpendicular_distance,
|
||||||
|
min_dist
|
||||||
|
)
|
||||||
|
) { //found a new minimum
|
||||||
|
min_dist = current_perpendicular_distance;
|
||||||
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
|
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||||
|
result_phantom_node.weight1 = current_edge.weight;
|
||||||
|
result_phantom_node.weight2 = INT_MAX;
|
||||||
|
result_phantom_node.location = nearest;
|
||||||
|
current_start_coordinate.lat = current_edge.lat1;
|
||||||
|
current_start_coordinate.lon = current_edge.lon1;
|
||||||
|
current_end_coordinate.lat = current_edge.lat2;
|
||||||
|
current_end_coordinate.lon = current_edge.lon2;
|
||||||
|
nearest_edge = current_edge;
|
||||||
|
found_a_nearest_edge = true;
|
||||||
|
} else if(
|
||||||
|
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||||
|
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||||
|
&& CoordinatesAreEquivalent(
|
||||||
|
current_start_coordinate,
|
||||||
|
FixedPointCoordinate(
|
||||||
|
current_edge.lat1,
|
||||||
|
current_edge.lon1
|
||||||
|
),
|
||||||
|
FixedPointCoordinate(
|
||||||
|
current_edge.lat2,
|
||||||
|
current_edge.lon2
|
||||||
|
),
|
||||||
|
current_end_coordinate
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
||||||
|
//SimpleLogger().Write() << "found bidirected edge on nodes " << current_edge.id << " and " << result_phantom_node.edgeBasedNode;
|
||||||
|
result_phantom_node.weight2 = current_edge.weight;
|
||||||
|
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
||||||
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
|
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
||||||
|
std::swap(current_end_coordinate, current_start_coordinate);
|
||||||
|
// SimpleLogger().Write() <<"case 2";
|
||||||
|
}
|
||||||
|
//SimpleLogger().Write() << "w1: " << result_phantom_node.weight1 << ", w2: " << result_phantom_node.weight2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//traverse children, prune if global mindist is smaller than local one
|
||||||
|
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||||
|
const int32_t child_id = current_tree_node.children[i];
|
||||||
|
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||||
|
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||||
|
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||||
|
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||||
|
if( current_min_max_dist < min_max_dist ) {
|
||||||
|
min_max_dist = current_min_max_dist;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_max_dist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_dist) { //upward pruning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double ratio = (found_a_nearest_edge ?
|
||||||
|
std::min(1., ApproximateDistance(current_start_coordinate,
|
||||||
|
result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate)
|
||||||
|
) : 0
|
||||||
|
);
|
||||||
|
result_phantom_node.weight1 *= ratio;
|
||||||
|
if(INT_MAX != result_phantom_node.weight2) {
|
||||||
|
result_phantom_node.weight2 *= (1.-ratio);
|
||||||
|
}
|
||||||
|
result_phantom_node.ratio = ratio;
|
||||||
|
|
||||||
|
//Hack to fix rounding errors and wandering via nodes.
|
||||||
|
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||||
|
result_phantom_node.location.lon = input_coordinate.lon;
|
||||||
|
}
|
||||||
|
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||||
|
result_phantom_node.location.lat = input_coordinate.lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_a_nearest_edge;
|
||||||
|
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
|
||||||
|
if(!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open()) {
|
||||||
|
thread_local_rtree_stream.reset(
|
||||||
|
new boost::filesystem::ifstream(
|
||||||
|
m_leaf_node_filename,
|
||||||
|
std::ios::in | std::ios::binary
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if(!thread_local_rtree_stream->good()) {
|
||||||
|
thread_local_rtree_stream->clear(std::ios::goodbit);
|
||||||
|
SimpleLogger().Write(logDEBUG) << "Resetting stale filestream";
|
||||||
|
}
|
||||||
|
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
|
||||||
|
thread_local_rtree_stream->seekg(seek_pos);
|
||||||
|
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double ComputePerpendicularDistance(
|
||||||
|
const FixedPointCoordinate& inputPoint,
|
||||||
|
const FixedPointCoordinate& source,
|
||||||
|
const FixedPointCoordinate& target,
|
||||||
|
FixedPointCoordinate& nearest, double *r) const {
|
||||||
|
const double x = static_cast<double>(inputPoint.lat);
|
||||||
|
const double y = static_cast<double>(inputPoint.lon);
|
||||||
|
const double a = static_cast<double>(source.lat);
|
||||||
|
const double b = static_cast<double>(source.lon);
|
||||||
|
const double c = static_cast<double>(target.lat);
|
||||||
|
const double d = static_cast<double>(target.lon);
|
||||||
|
double p,q,mX,nY;
|
||||||
|
if(fabs(a-c) > FLT_EPSILON){
|
||||||
|
const double m = (d-b)/(c-a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||||
|
q = b + m*(p - a);
|
||||||
|
} else {
|
||||||
|
p = c;
|
||||||
|
q = y;
|
||||||
|
}
|
||||||
|
nY = (d*p - c*q)/(a*d - b*c);
|
||||||
|
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
|
||||||
|
// not calculate the explicit values of m an n as we
|
||||||
|
// are just interested in the ratio
|
||||||
|
if(std::isnan(mX)) {
|
||||||
|
*r = (target == inputPoint) ? 1. : 0.;
|
||||||
|
} else {
|
||||||
|
*r = mX;
|
||||||
|
}
|
||||||
|
if(*r<=0.){
|
||||||
|
nearest.lat = source.lat;
|
||||||
|
nearest.lon = source.lon;
|
||||||
|
return ((b - y)*(b - y) + (a - x)*(a - x));
|
||||||
|
// return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x)));
|
||||||
|
} else if(*r >= 1.){
|
||||||
|
nearest.lat = target.lat;
|
||||||
|
nearest.lon = target.lon;
|
||||||
|
return ((d - y)*(d - y) + (c - x)*(c - x));
|
||||||
|
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
|
||||||
|
}
|
||||||
|
// point lies in between
|
||||||
|
nearest.lat = p;
|
||||||
|
nearest.lon = q;
|
||||||
|
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
|
||||||
|
return (p-x)*(p-x) + (q-y)*(q-y);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CoordinatesAreEquivalent(const FixedPointCoordinate & a, const FixedPointCoordinate & b, const FixedPointCoordinate & c, const FixedPointCoordinate & d) const {
|
||||||
|
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
|
||||||
|
return (std::fabs(d1 - d2) < FLT_EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
|
||||||
|
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* STATICRTREE_H_ */
|
||||||
@@ -21,12 +21,12 @@
|
|||||||
#ifndef TURNINSTRUCTIONS_H_
|
#ifndef TURNINSTRUCTIONS_H_
|
||||||
#define TURNINSTRUCTIONS_H_
|
#define TURNINSTRUCTIONS_H_
|
||||||
|
|
||||||
#include <string>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
typedef unsigned char TurnInstruction;
|
typedef unsigned char TurnInstruction;
|
||||||
|
|
||||||
//This is a hack until c++0x is available enough to use scoped enums
|
//This is a hack until c++0x is available enough to use scoped enums
|
||||||
struct TurnInstructionsClass {
|
struct TurnInstructionsClass : boost::noncopyable {
|
||||||
|
|
||||||
const static TurnInstruction NoTurn = 0; //Give no instruction at all
|
const static TurnInstruction NoTurn = 0; //Give no instruction at all
|
||||||
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
|
const static TurnInstruction GoStraight = 1; //Tell user to go straight!
|
||||||
@@ -44,48 +44,14 @@ struct TurnInstructionsClass {
|
|||||||
const static TurnInstruction StayOnRoundAbout = 13;
|
const static TurnInstruction StayOnRoundAbout = 13;
|
||||||
const static TurnInstruction StartAtEndOfStreet = 14;
|
const static TurnInstruction StartAtEndOfStreet = 14;
|
||||||
const static TurnInstruction ReachedYourDestination = 15;
|
const static TurnInstruction ReachedYourDestination = 15;
|
||||||
|
const static TurnInstruction EnterAgainstAllowedDirection = 16;
|
||||||
|
const static TurnInstruction LeaveAgainstAllowedDirection = 17;
|
||||||
|
|
||||||
const static TurnInstruction AccessRestrictionFlag = 128;
|
const static TurnInstruction AccessRestrictionFlag = 128;
|
||||||
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
|
const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning.
|
||||||
|
|
||||||
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
|
const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag
|
||||||
|
|
||||||
// std::string TurnStrings[16];
|
|
||||||
// std::string Ordinals[12];
|
|
||||||
|
|
||||||
//This is a hack until c++0x is available enough to use initializer lists.
|
|
||||||
// TurnInstructionsClass(){
|
|
||||||
// TurnStrings [0] = "";
|
|
||||||
// TurnStrings [1] = "Continue";
|
|
||||||
// TurnStrings [2] = "Turn slight right";
|
|
||||||
// TurnStrings [3] = "Turn right";
|
|
||||||
// TurnStrings [4] = "Turn sharp right";
|
|
||||||
// TurnStrings [5] = "U-Turn";
|
|
||||||
// TurnStrings [6] = "Turn sharp left";
|
|
||||||
// TurnStrings [7] = "Turn left";
|
|
||||||
// TurnStrings [8] = "Turn slight left";
|
|
||||||
// TurnStrings [9] = "Reach via point";
|
|
||||||
// TurnStrings[10] = "Head";
|
|
||||||
// TurnStrings[11] = "Enter roundabout";
|
|
||||||
// TurnStrings[12] = "Leave roundabout";
|
|
||||||
// TurnStrings[13] = "Stay on roundabout";
|
|
||||||
// TurnStrings[14] = "Start";
|
|
||||||
// TurnStrings[15] = "You have reached your destination";
|
|
||||||
//
|
|
||||||
// Ordinals[0] = "zeroth";
|
|
||||||
// Ordinals[1] = "first";
|
|
||||||
// Ordinals[2] = "second";
|
|
||||||
// Ordinals[3] = "third";
|
|
||||||
// Ordinals[4] = "fourth";
|
|
||||||
// Ordinals[5] = "fifth";
|
|
||||||
// Ordinals[6] = "sixth";
|
|
||||||
// Ordinals[7] = "seventh";
|
|
||||||
// Ordinals[8] = "eighth";
|
|
||||||
// Ordinals[9] = "nineth";
|
|
||||||
// Ordinals[10] = "tenth";
|
|
||||||
// Ordinals[11] = "one of the too many";
|
|
||||||
// };
|
|
||||||
|
|
||||||
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
|
static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) {
|
||||||
if(angle >= 23 && angle < 67) {
|
if(angle >= 23 && angle < 67) {
|
||||||
return TurnSharpRight;
|
return TurnSharpRight;
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TIMEUTIL_H_
|
|
||||||
#define TIMEUTIL_H_
|
|
||||||
|
|
||||||
#include <climits>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <winsock.h>
|
|
||||||
void gettimeofday(struct timeval* t,void* timezone)
|
|
||||||
{ struct _timeb timebuffer;
|
|
||||||
_ftime( &timebuffer );
|
|
||||||
t->tv_sec=timebuffer.time;
|
|
||||||
t->tv_usec=1000*timebuffer.millitm;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <boost/functional/hash.hpp>
|
|
||||||
#else
|
|
||||||
#include <tr1/functional_hash.h>
|
|
||||||
#endif
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
/** Returns a timestamp (now) in seconds (incl. a fractional part). */
|
|
||||||
static inline double get_timestamp() {
|
|
||||||
struct timeval tp;
|
|
||||||
gettimeofday(&tp, NULL);
|
|
||||||
return double(tp.tv_sec) + tp.tv_usec / 1000000.;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline double y2lat(double a) { return 180/M_PI * (2 * atan(exp(a*M_PI/180)) - M_PI/2); }
|
|
||||||
static inline double lat2y(double a) { return 180/M_PI * log(tan(M_PI/4+a*(M_PI/180)/2)); }
|
|
||||||
|
|
||||||
static inline unsigned boost_thread_id_hash(boost::thread::id const& id) {
|
|
||||||
std::stringstream ostr;
|
|
||||||
ostr << id;
|
|
||||||
std::tr1::hash<std::string> h;
|
|
||||||
return h(ostr.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* TIMEUTIL_H_ */
|
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
table1.resize(2 << 16);
|
table1.resize(2 << 16);
|
||||||
table2.resize(2 << 16);
|
table2.resize(2 << 16);
|
||||||
for(unsigned i = 0; i < (2 << 16); ++i) {
|
for(unsigned i = 0; i < (2 << 16); ++i) {
|
||||||
table1[i] = i; table2[i];
|
table1[i] = i; table2[i] = i;
|
||||||
}
|
}
|
||||||
std::random_shuffle(table1.begin(), table1.end());
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
std::random_shuffle(table2.begin(), table2.end());
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
@@ -75,8 +75,8 @@ public:
|
|||||||
table3.resize(1 << 8);
|
table3.resize(1 << 8);
|
||||||
table4.resize(1 << 8);
|
table4.resize(1 << 8);
|
||||||
for(unsigned i = 0; i < (1 << 8); ++i) {
|
for(unsigned i = 0; i < (1 << 8); ++i) {
|
||||||
table1[i] = i; table2[i];
|
table1[i] = i; table2[i] = i;
|
||||||
table3[i] = i; table4[i];
|
table3[i] = i; table4[i] = i;
|
||||||
}
|
}
|
||||||
std::random_shuffle(table1.begin(), table1.end());
|
std::random_shuffle(table1.begin(), table1.end());
|
||||||
std::random_shuffle(table2.begin(), table2.end());
|
std::random_shuffle(table2.begin(), table2.end());
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef XORFASTHASHSTORAGE_H_
|
#ifndef XORFASTHASHSTORAGE_H_
|
||||||
#define XORFASTHASHSTORAGE_H_
|
#define XORFASTHASHSTORAGE_H_
|
||||||
|
|
||||||
|
#include "XORFastHash.h"
|
||||||
|
|
||||||
#include <climits>
|
#include <climits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#include "XORFastHash.h"
|
|
||||||
|
|
||||||
template< typename NodeID, typename Key >
|
template< typename NodeID, typename Key >
|
||||||
class XORFastHashStorage {
|
class XORFastHashStorage {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -21,19 +21,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef BASE_DESCRIPTOR_H_
|
#ifndef BASE_DESCRIPTOR_H_
|
||||||
#define BASE_DESCRIPTOR_H_
|
#define BASE_DESCRIPTOR_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../DataStructures/SearchEngine.h"
|
||||||
|
#include "../Server/BasicDatastructures.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
|
|
||||||
#include "../Plugins/RawRouteData.h"
|
|
||||||
|
|
||||||
struct _DescriptorConfig {
|
struct _DescriptorConfig {
|
||||||
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
|
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(true), z(18) {}
|
||||||
bool instructions;
|
bool instructions;
|
||||||
@@ -42,13 +44,12 @@ struct _DescriptorConfig {
|
|||||||
unsigned short z;
|
unsigned short z;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class SearchEngineT>
|
|
||||||
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, SearchEngineT &sEngine) = 0;
|
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
|
||||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,11 +32,14 @@ inline double DescriptionFactory::RadianToDegree(const double radian) const {
|
|||||||
return radian * (180/M_PI);
|
return radian * (180/M_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
double DescriptionFactory::GetBearing(const _Coordinate& A, const _Coordinate& B) const {
|
double DescriptionFactory::GetBearing(
|
||||||
double deltaLong = DegreeToRadian(B.lon/100000. - A.lon/100000.);
|
const FixedPointCoordinate & A,
|
||||||
|
const FixedPointCoordinate & B
|
||||||
|
) const {
|
||||||
|
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||||
|
|
||||||
double lat1 = DegreeToRadian(A.lat/100000.);
|
double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||||
double lat2 = DegreeToRadian(B.lat/100000.);
|
double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
||||||
|
|
||||||
double y = sin(deltaLong) * cos(lat2);
|
double y = sin(deltaLong) * cos(lat2);
|
||||||
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
||||||
@@ -59,7 +62,7 @@ void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
|
|||||||
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
|
pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
|
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data ) {
|
||||||
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
||||||
pathDescription.back().nameID = data.nameID;
|
pathDescription.back().nameID = data.nameID;
|
||||||
} else {
|
} else {
|
||||||
@@ -82,7 +85,7 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
|
|||||||
pc.printUnencodedString(pathDescription, output);
|
pc.printUnencodedString(pathDescription, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) {
|
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
||||||
|
|
||||||
if(0 == pathDescription.size())
|
if(0 == pathDescription.size())
|
||||||
return;
|
return;
|
||||||
@@ -91,7 +94,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
|||||||
/** starts at index 1 */
|
/** starts at index 1 */
|
||||||
pathDescription[0].length = 0;
|
pathDescription[0].length = 0;
|
||||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
pathDescription[i].length = ApproximateDistanceByEuclid(pathDescription[i-1].location, pathDescription[i].location);
|
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||||
}
|
}
|
||||||
|
|
||||||
double lengthOfSegment = 0;
|
double lengthOfSegment = 0;
|
||||||
@@ -123,7 +126,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
|||||||
// || std::string::npos != string0.find(string1+" ;")
|
// || std::string::npos != string0.find(string1+" ;")
|
||||||
// || std::string::npos != string0.find("; "+string1)
|
// || std::string::npos != string0.find("; "+string1)
|
||||||
// ){
|
// ){
|
||||||
// INFO("->next correct: " << string0 << " contains " << string1);
|
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||||
// for(; lastTurn != i; ++lastTurn)
|
// for(; lastTurn != i; ++lastTurn)
|
||||||
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
@@ -132,7 +135,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
|||||||
// || std::string::npos != string1.find(string0+" ;")
|
// || std::string::npos != string1.find(string0+" ;")
|
||||||
// || std::string::npos != string1.find("; "+string0)
|
// || std::string::npos != string1.find("; "+string0)
|
||||||
// ){
|
// ){
|
||||||
// INFO("->prev correct: " << string1 << " contains " << string0);
|
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||||
// }
|
// }
|
||||||
@@ -153,24 +156,24 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
|||||||
|
|
||||||
|
|
||||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||||
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
|
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
|
||||||
assert(pathDescription[i].necessary);
|
assert(pathDescription[i].necessary);
|
||||||
lengthOfSegment = 0;
|
lengthOfSegment = 0;
|
||||||
durationOfSegment = 0;
|
durationOfSegment = 0;
|
||||||
indexOfSegmentBegin = i;
|
indexOfSegmentBegin = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INFO("#segs: " << pathDescription.size());
|
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||||
|
|
||||||
//Post-processing to remove empty or nearly empty path segments
|
//Post-processing to remove empty or nearly empty path segments
|
||||||
if(FLT_EPSILON > pathDescription.back().length) {
|
if(FLT_EPSILON > pathDescription.back().length) {
|
||||||
// INFO("#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length);
|
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << targetPhantom.ratio << ", length: " << pathDescription.back().length;
|
||||||
if(pathDescription.size() > 2){
|
if(pathDescription.size() > 2){
|
||||||
pathDescription.pop_back();
|
pathDescription.pop_back();
|
||||||
pathDescription.back().necessary = true;
|
pathDescription.back().necessary = true;
|
||||||
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||||
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||||
// INFO("Deleting last turn instruction");
|
// SimpleLogger().Write() << "Deleting last turn instruction";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
|
pathDescription[indexOfSegmentBegin].duration *= (1.-targetPhantom.ratio);
|
||||||
@@ -182,7 +185,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe
|
|||||||
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||||
pathDescription[0].necessary = true;
|
pathDescription[0].necessary = true;
|
||||||
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||||
// INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length);
|
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pathDescription[0].duration *= startPhantom.ratio;
|
pathDescription[0].duration *= startPhantom.ratio;
|
||||||
|
|||||||
@@ -21,16 +21,16 @@
|
|||||||
#ifndef DESCRIPTIONFACTORY_H_
|
#ifndef DESCRIPTIONFACTORY_H_
|
||||||
#define DESCRIPTIONFACTORY_H_
|
#define DESCRIPTIONFACTORY_H_
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../Algorithms/DouglasPeucker.h"
|
#include "../Algorithms/DouglasPeucker.h"
|
||||||
#include "../Algorithms/PolylineCompressor.h"
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
/* This class is fed with all way segments in consecutive order
|
/* This class is fed with all way segments in consecutive order
|
||||||
* and produces the description plus the encoded polyline */
|
* and produces the description plus the encoded polyline */
|
||||||
@@ -40,8 +40,6 @@ class DescriptionFactory {
|
|||||||
PolylineCompressor pc;
|
PolylineCompressor pc;
|
||||||
PhantomNode startPhantom, targetPhantom;
|
PhantomNode startPhantom, targetPhantom;
|
||||||
|
|
||||||
typedef SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > SearchEngineT;
|
|
||||||
|
|
||||||
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:
|
||||||
@@ -53,13 +51,9 @@ public:
|
|||||||
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
|
_RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
|
||||||
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
|
void BuildDurationAndLengthStrings(const double distance, const unsigned time) {
|
||||||
//compute distance/duration for route summary
|
//compute distance/duration for route summary
|
||||||
std::ostringstream s;
|
intToString(round(distance), lengthString);
|
||||||
s << round(distance);
|
|
||||||
lengthString = s.str();
|
|
||||||
int travelTime = time/10 + 1;
|
int travelTime = time/10 + 1;
|
||||||
s.str("");
|
intToString(travelTime, durationString);
|
||||||
s << travelTime;
|
|
||||||
durationString = s.str();
|
|
||||||
}
|
}
|
||||||
} summary;
|
} summary;
|
||||||
|
|
||||||
@@ -69,15 +63,15 @@ public:
|
|||||||
std::vector <SegmentInformation> pathDescription;
|
std::vector <SegmentInformation> pathDescription;
|
||||||
DescriptionFactory();
|
DescriptionFactory();
|
||||||
virtual ~DescriptionFactory();
|
virtual ~DescriptionFactory();
|
||||||
double GetBearing(const _Coordinate& C, const _Coordinate& B) const;
|
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
||||||
void AppendEncodedPolylineString(std::string &output);
|
void AppendEncodedPolylineString(std::string &output);
|
||||||
void AppendUnencodedPolylineString(std::string &output);
|
void AppendUnencodedPolylineString(std::string &output);
|
||||||
void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
|
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
|
||||||
void BuildRouteSummary(const double distance, const unsigned time);
|
void BuildRouteSummary(const double distance, const unsigned time);
|
||||||
void SetStartSegment(const PhantomNode & startPhantom);
|
void SetStartSegment(const PhantomNode & startPhantom);
|
||||||
void SetEndSegment(const PhantomNode & startPhantom);
|
void SetEndSegment(const PhantomNode & startPhantom);
|
||||||
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
||||||
void Run(const SearchEngineT &sEngine, const unsigned zoomLevel);
|
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DESCRIPTIONFACTORY_H_ */
|
#endif /* DESCRIPTIONFACTORY_H_ */
|
||||||
|
|||||||
@@ -21,24 +21,25 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef GPX_DESCRIPTOR_H_
|
#ifndef GPX_DESCRIPTOR_H_
|
||||||
#define GPX_DESCRIPTOR_H_
|
#define GPX_DESCRIPTOR_H_
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
template<class SearchEngineT>
|
#include <boost/foreach.hpp>
|
||||||
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
|
|
||||||
|
class GPXDescriptor : public BaseDescriptor{
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
_DescriptorConfig config;
|
||||||
_Coordinate current;
|
FixedPointCoordinate current;
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
public:
|
public:
|
||||||
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
|
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
||||||
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
reply.content += "<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 += "<rte>";
|
reply.content += "<rte>";
|
||||||
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
|
if(rawRoute.lengthOfShortestPath != INT_MAX && rawRoute.computedShortestPath.size()) {
|
||||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
||||||
@@ -46,7 +47,7 @@ public:
|
|||||||
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
||||||
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||||
|
|
||||||
BOOST_FOREACH(_PathData pathData, rawRoute.computedShortestPath) {
|
BOOST_FOREACH(const _PathData & pathData, rawRoute.computedShortestPath) {
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||||
|
|
||||||
convertInternalLatLonToString(current.lat, tmp);
|
convertInternalLatLonToString(current.lat, tmp);
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef JSON_DESCRIPTOR_H_
|
#ifndef JSON_DESCRIPTOR_H_
|
||||||
#define JSON_DESCRIPTOR_H_
|
#define JSON_DESCRIPTOR_H_
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
#include "DescriptionFactory.h"
|
#include "DescriptionFactory.h"
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
@@ -34,15 +29,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../Util/Azimuth.h"
|
#include "../Util/Azimuth.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
template<class SearchEngineT>
|
#include <boost/bind.hpp>
|
||||||
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
#include <boost/lambda/lambda.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
class JSONDescriptor : public BaseDescriptor{
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
_DescriptorConfig config;
|
||||||
DescriptionFactory descriptionFactory;
|
DescriptionFactory descriptionFactory;
|
||||||
DescriptionFactory alternateDescriptionFactory;
|
DescriptionFactory alternateDescriptionFactory;
|
||||||
_Coordinate current;
|
FixedPointCoordinate current;
|
||||||
unsigned numberOfEnteredRestrictedAreas;
|
unsigned numberOfEnteredRestrictedAreas;
|
||||||
struct {
|
struct RoundAbout{
|
||||||
|
RoundAbout() :
|
||||||
|
startIndex(INT_MAX),
|
||||||
|
nameID(INT_MAX),
|
||||||
|
leaveAtExit(INT_MAX)
|
||||||
|
{}
|
||||||
int startIndex;
|
int startIndex;
|
||||||
int nameID;
|
int nameID;
|
||||||
int leaveAtExit;
|
int leaveAtExit;
|
||||||
@@ -68,7 +72,7 @@ public:
|
|||||||
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
JSONDescriptor() : numberOfEnteredRestrictedAreas(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, SearchEngineT &sEngine) {
|
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
||||||
|
|
||||||
WriteHeaderToOutput(reply.content);
|
WriteHeaderToOutput(reply.content);
|
||||||
|
|
||||||
@@ -246,7 +250,7 @@ public:
|
|||||||
reply.content += "}";
|
reply.content += "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, SearchEngineT &sEngine, RouteNames & routeNames) {
|
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
|
||||||
/*** extract names for both alternatives ***/
|
/*** extract names for both alternatives ***/
|
||||||
|
|
||||||
Segment shortestSegment1, shortestSegment2;
|
Segment shortestSegment1, shortestSegment2;
|
||||||
@@ -262,23 +266,25 @@ public:
|
|||||||
std::vector<Segment> shortestDifference(shortestSegments.size());
|
std::vector<Segment> shortestDifference(shortestSegments.size());
|
||||||
std::vector<Segment> alternativeDifference(alternativeSegments.size());
|
std::vector<Segment> alternativeDifference(alternativeSegments.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(shortestSegments.begin(), shortestSegments.end(), alternativeSegments.begin(), alternativeSegments.end(), shortestDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
||||||
if(0 < shortestDifference.size() ) {
|
int size_of_difference = shortestDifference.size();
|
||||||
unsigned i = 0;
|
if(0 < size_of_difference ) {
|
||||||
while( i < shortestDifference.size() && shortestDifference[i].nameID == shortestSegments[0].nameID) {
|
int i = 0;
|
||||||
|
while( i < size_of_difference && shortestDifference[i].nameID == shortestSegments[0].nameID) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(i < shortestDifference.size()) {
|
if(i < size_of_difference ) {
|
||||||
shortestSegment2 = shortestDifference[i];
|
shortestSegment2 = shortestDifference[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(alternativeSegments.begin(), alternativeSegments.end(), shortestSegments.begin(), shortestSegments.end(), alternativeDifference.begin(), boost::bind(&Segment::nameID, _1) < boost::bind(&Segment::nameID, _2) );
|
||||||
if(0 < alternativeDifference.size() ) {
|
size_of_difference = alternativeDifference.size();
|
||||||
unsigned i = 0;
|
if(0 < size_of_difference ) {
|
||||||
while( i < alternativeDifference.size() && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
|
int i = 0;
|
||||||
|
while( i < size_of_difference && alternativeDifference[i].nameID == alternativeSegments[0].nameID) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
if(i < alternativeDifference.size()) {
|
if(i < size_of_difference ) {
|
||||||
alternativeSegment2 = alternativeDifference[i];
|
alternativeSegment2 = alternativeDifference[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -292,7 +298,7 @@ public:
|
|||||||
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
|
routeNames.shortestPathName2 = sEngine.GetEscapedNameForNameID(shortestSegment2.nameID);
|
||||||
|
|
||||||
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
|
routeNames.alternativePathName1 = sEngine.GetEscapedNameForNameID(alternativeSegment1.nameID);
|
||||||
routeNames.alternativePathName2 += sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
|
routeNames.alternativePathName2 = sEngine.GetEscapedNameForNameID(alternativeSegment2.nameID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +308,7 @@ public:
|
|||||||
"\"status\":";
|
"\"status\":";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngineT &sEngine, std::vector<Segment> & segmentVector) {
|
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
|
||||||
//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]
|
||||||
|
|||||||
-1
Submodule Docs deleted from f7150057d5
@@ -0,0 +1,3 @@
|
|||||||
|
The javascript based web client is a seperate project available at
|
||||||
|
|
||||||
|
https://github.com/DennisSchiefer/Project-OSRM-Web
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BaseParser.h"
|
||||||
|
|
||||||
|
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
|
||||||
|
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
|
||||||
|
luaState = se.getLuaStateForThreadID(0);
|
||||||
|
ReadUseRestrictionsSetting();
|
||||||
|
ReadRestrictionExceptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseParser::ReadUseRestrictionsSetting() {
|
||||||
|
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) {
|
||||||
|
throw OSRMException(
|
||||||
|
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if( lua_isboolean( luaState, -1) ) {
|
||||||
|
use_turn_restrictions = lua_toboolean(luaState, -1);
|
||||||
|
}
|
||||||
|
if( use_turn_restrictions ) {
|
||||||
|
SimpleLogger().Write() << "Using turn restrictions";
|
||||||
|
} else {
|
||||||
|
SimpleLogger().Write() << "Ignoring turn restrictions";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseParser::ReadRestrictionExceptions() {
|
||||||
|
if(lua_function_exists(luaState, "get_exceptions" )) {
|
||||||
|
//get list of turn restriction exceptions
|
||||||
|
luabind::call_function<void>(
|
||||||
|
luaState,
|
||||||
|
"get_exceptions",
|
||||||
|
boost::ref(restriction_exceptions)
|
||||||
|
);
|
||||||
|
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
|
||||||
|
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
|
||||||
|
SimpleLogger().Write() << " " << str;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SimpleLogger().Write() << "Found no exceptions to turn restrictions";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseParser::report_errors(lua_State *L, const int status) const {
|
||||||
|
if( 0!=status ) {
|
||||||
|
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
|
||||||
|
lua_pop(L, 1); // remove error message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
||||||
|
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
||||||
|
if(2 > w.path.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BaseParser::ShouldIgnoreRestriction(const std::string& except_tag_string) const {
|
||||||
|
//should this restriction be ignored? yes if there's an overlap between:
|
||||||
|
//a) the list of modes in the except tag of the restriction (except_tag_string), ex: except=bus;bicycle
|
||||||
|
//b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle]
|
||||||
|
|
||||||
|
if( "" == except_tag_string ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Be warned, this is quadratic work here, but we assume that
|
||||||
|
//only a few exceptions are actually defined.
|
||||||
|
std::vector<std::string> exceptions;
|
||||||
|
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
|
||||||
|
BOOST_FOREACH(std::string& str, exceptions) {
|
||||||
|
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
+26
-15
@@ -21,29 +21,40 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef BASEPARSER_H_
|
#ifndef BASEPARSER_H_
|
||||||
#define BASEPARSER_H_
|
#define BASEPARSER_H_
|
||||||
|
|
||||||
|
#include "ExtractorCallbacks.h"
|
||||||
|
#include "ScriptingEnvironment.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "ScriptingEnvironment.h"
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
template<class ExternalMemoryT, typename NodeT, typename RestrictionT, typename WayT>
|
class BaseParser : boost::noncopyable {
|
||||||
class BaseParser {
|
|
||||||
public:
|
public:
|
||||||
|
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||||
virtual ~BaseParser() {}
|
virtual ~BaseParser() {}
|
||||||
virtual bool Init() = 0;
|
virtual bool ReadHeader() = 0;
|
||||||
virtual void RegisterCallbacks(ExternalMemoryT * externalMemory) = 0;
|
|
||||||
virtual void RegisterScriptingEnvironment(ScriptingEnvironment & _se) = 0;
|
|
||||||
virtual bool Parse() = 0;
|
virtual bool Parse() = 0;
|
||||||
|
|
||||||
void report_errors(lua_State *L, int status) {
|
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
|
||||||
if ( status!=0 ) {
|
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
|
||||||
std::cerr << "-- " << lua_tostring(L, -1) << std::endl;
|
virtual void report_errors(lua_State *L, const int status) const;
|
||||||
lua_pop(L, 1); // remove error message
|
|
||||||
}
|
protected:
|
||||||
}
|
virtual void ReadUseRestrictionsSetting();
|
||||||
|
virtual void ReadRestrictionExceptions();
|
||||||
|
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
|
||||||
|
|
||||||
|
ExtractorCallbacks* extractor_callbacks;
|
||||||
|
ScriptingEnvironment& scriptingEnvironment;
|
||||||
|
lua_State* luaState;
|
||||||
|
std::vector<std::string> restriction_exceptions;
|
||||||
|
bool use_turn_restrictions;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,38 +20,38 @@
|
|||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include "ExtractionContainers.h"
|
||||||
|
|
||||||
void ExtractionContainers::PrepareData(const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM) {
|
void ExtractionContainers::PrepareData(const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM) {
|
||||||
try {
|
try {
|
||||||
unsigned usedNodeCounter = 0;
|
unsigned usedNodeCounter = 0;
|
||||||
unsigned usedEdgeCounter = 0;
|
unsigned usedEdgeCounter = 0;
|
||||||
double time = get_timestamp();
|
double time = get_timestamp();
|
||||||
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
|
boost::uint64_t memory_to_use = static_cast<boost::uint64_t>(amountOfRAM) * 1024 * 1024 * 1024;
|
||||||
|
|
||||||
cout << "[extractor] Sorting used nodes ... " << flush;
|
std::cout << "[extractor] Sorting used nodes ... " << std::flush;
|
||||||
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
|
stxxl::sort(usedNodeIDs.begin(), usedNodeIDs.end(), Cmp(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
cout << "[extractor] Erasing duplicate nodes ... " << flush;
|
std::cout << "[extractor] Erasing duplicate nodes ... " << std::flush;
|
||||||
stxxl::vector<NodeID>::iterator NewEnd = unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
|
stxxl::vector<NodeID>::iterator NewEnd = std::unique ( usedNodeIDs.begin(),usedNodeIDs.end() ) ;
|
||||||
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
|
usedNodeIDs.resize ( NewEnd - usedNodeIDs.begin() );
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
cout << "[extractor] Sorting all nodes ... " << flush;
|
std::cout << "[extractor] Sorting all nodes ... " << std::flush;
|
||||||
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
|
stxxl::sort(allNodes.begin(), allNodes.end(), CmpNodeByID(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
cout << "[extractor] Sorting used ways ... " << flush;
|
std::cout << "[extractor] Sorting used ways ... " << std::flush;
|
||||||
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
|
stxxl::sort(wayStartEndVector.begin(), wayStartEndVector.end(), CmpWayByID(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
cout << "[extractor] Sorting restrctns. by from... " << flush;
|
std::cout << "[extractor] Sorting restrctns. by from... " << std::flush;
|
||||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
|
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByFrom(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
cout << "[extractor] Fixing restriction starts ... " << flush;
|
std::cout << "[extractor] Fixing restriction starts ... " << std::flush;
|
||||||
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
|
STXXLRestrictionsVector::iterator restrictionsIT = restrictionsVector.begin();
|
||||||
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
STXXLWayIDStartEndVector::iterator wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
||||||
|
|
||||||
@@ -79,16 +79,16 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
++restrictionsIT;
|
++restrictionsIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
cout << "[extractor] Sorting restrctns. by to ... " << flush;
|
std::cout << "[extractor] Sorting restrctns. by to ... " << std::flush;
|
||||||
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
|
stxxl::sort(restrictionsVector.begin(), restrictionsVector.end(), CmpRestrictionContainerByTo(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
unsigned usableRestrictionsCounter(0);
|
unsigned usableRestrictionsCounter(0);
|
||||||
cout << "[extractor] Fixing restriction ends ... " << flush;
|
std::cout << "[extractor] Fixing restriction ends ... " << std::flush;
|
||||||
restrictionsIT = restrictionsVector.begin();
|
restrictionsIT = restrictionsVector.begin();
|
||||||
wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
wayStartAndEndEdgeIT = wayStartEndVector.begin();
|
||||||
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
while(wayStartAndEndEdgeIT != wayStartEndVector.end() && restrictionsIT != restrictionsVector.end()) {
|
||||||
@@ -116,24 +116,26 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
}
|
}
|
||||||
++restrictionsIT;
|
++restrictionsIT;
|
||||||
}
|
}
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
INFO("usable restrictions: " << usableRestrictionsCounter );
|
SimpleLogger().Write() << "usable restrictions: " << usableRestrictionsCounter;
|
||||||
//serialize restrictions
|
//serialize restrictions
|
||||||
ofstream restrictionsOutstream;
|
std::ofstream restrictionsOutstream;
|
||||||
restrictionsOutstream.open(restrictionsFileName.c_str(), ios::binary);
|
restrictionsOutstream.open(restrictionsFileName.c_str(), std::ios::binary);
|
||||||
|
restrictionsOutstream.write((char*)&uuid, sizeof(UUID));
|
||||||
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
restrictionsOutstream.write((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
||||||
for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
|
for(restrictionsIT = restrictionsVector.begin(); restrictionsIT != restrictionsVector.end(); ++restrictionsIT) {
|
||||||
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
|
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
|
||||||
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(_Restriction));
|
restrictionsOutstream.write((char *)&(restrictionsIT->restriction), sizeof(TurnRestriction));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restrictionsOutstream.close();
|
restrictionsOutstream.close();
|
||||||
|
|
||||||
ofstream fout;
|
std::ofstream fout;
|
||||||
fout.open(outputFileName.c_str(), ios::binary);
|
fout.open(output_file_name.c_str(), std::ios::binary);
|
||||||
|
fout.write((char*)&uuid, sizeof(UUID));
|
||||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
cout << "[extractor] Confirming/Writing used nodes ... " << flush;
|
std::cout << "[extractor] Confirming/Writing used nodes ... " << std::flush;
|
||||||
|
|
||||||
STXXLNodeVector::iterator nodesIT = allNodes.begin();
|
STXXLNodeVector::iterator nodesIT = allNodes.begin();
|
||||||
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
|
STXXLNodeIDVector::iterator usedNodeIDsIT = usedNodeIDs.begin();
|
||||||
@@ -154,24 +156,24 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
cout << "[extractor] setting number of nodes ... " << flush;
|
std::cout << "[extractor] setting number of nodes ... " << std::flush;
|
||||||
ios::pos_type positionInFile = fout.tellp();
|
std::ios::pos_type positionInFile = fout.tellp();
|
||||||
fout.seekp(ios::beg);
|
fout.seekp(std::ios::beg+sizeof(UUID));
|
||||||
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
fout.write((char*)&usedNodeCounter, sizeof(unsigned));
|
||||||
fout.seekp(positionInFile);
|
fout.seekp(positionInFile);
|
||||||
|
|
||||||
cout << "ok" << endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
// Sort edges by start.
|
// Sort edges by start.
|
||||||
cout << "[extractor] Sorting edges by start ... " << flush;
|
std::cout << "[extractor] Sorting edges by start ... " << std::flush;
|
||||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
|
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByStartID(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
cout << "[extractor] Setting start coords ... " << flush;
|
std::cout << "[extractor] Setting start coords ... " << std::flush;
|
||||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
fout.write((char*)&usedEdgeCounter, 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();
|
nodesIT = allNodes.begin();
|
||||||
@@ -191,16 +193,16 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
++edgeIT;
|
++edgeIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << 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
|
||||||
cout << "[extractor] Sorting edges by target ... " << flush;
|
std::cout << "[extractor] Sorting edges by target ... " << std::flush;
|
||||||
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
|
stxxl::sort(allEdges.begin(), allEdges.end(), CmpEdgeByTargetID(), memory_to_use);
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
|
|
||||||
cout << "[extractor] Setting target coords ... " << 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();
|
nodesIT = allNodes.begin();
|
||||||
edgeIT = allEdges.begin();
|
edgeIT = allEdges.begin();
|
||||||
@@ -231,22 +233,22 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
fout.write((char*)&edgeIT->target, sizeof(unsigned));
|
fout.write((char*)&edgeIT->target, sizeof(unsigned));
|
||||||
fout.write((char*)&intDist, sizeof(int));
|
fout.write((char*)&intDist, sizeof(int));
|
||||||
switch(edgeIT->direction) {
|
switch(edgeIT->direction) {
|
||||||
case _Way::notSure:
|
case ExtractionWay::notSure:
|
||||||
fout.write((char*)&zero, sizeof(short));
|
fout.write((char*)&zero, sizeof(short));
|
||||||
break;
|
break;
|
||||||
case _Way::oneway:
|
case ExtractionWay::oneway:
|
||||||
fout.write((char*)&one, sizeof(short));
|
fout.write((char*)&one, sizeof(short));
|
||||||
break;
|
break;
|
||||||
case _Way::bidirectional:
|
case ExtractionWay::bidirectional:
|
||||||
fout.write((char*)&zero, sizeof(short));
|
fout.write((char*)&zero, sizeof(short));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case _Way::opposite:
|
case ExtractionWay::opposite:
|
||||||
fout.write((char*)&one, sizeof(short));
|
fout.write((char*)&one, sizeof(short));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cerr << "[error] edge with no direction: " << edgeIT->direction << endl;
|
std::cerr << "[error] edge with no direction: " << edgeIT->direction << std::endl;
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fout.write((char*)&intWeight, sizeof(int));
|
fout.write((char*)&intWeight, sizeof(int));
|
||||||
@@ -256,33 +258,34 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
|
fout.write((char*)&edgeIT->isRoundabout, sizeof(bool));
|
||||||
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
||||||
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
||||||
|
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
|
||||||
|
++usedEdgeCounter;
|
||||||
}
|
}
|
||||||
++usedEdgeCounter;
|
|
||||||
++edgeIT;
|
++edgeIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
cout << "[extractor] setting number of edges ... " << flush;
|
std::cout << "[extractor] setting number of edges ... " << std::flush;
|
||||||
|
|
||||||
fout.seekp(positionInFile);
|
fout.seekp(positionInFile);
|
||||||
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
fout.write((char*)&usedEdgeCounter, sizeof(unsigned));
|
||||||
fout.close();
|
fout.close();
|
||||||
cout << "ok" << endl;
|
std::cout << "ok" << std::endl;
|
||||||
time = get_timestamp();
|
time = get_timestamp();
|
||||||
cout << "[extractor] writing street name index ... " << flush;
|
std::cout << "[extractor] writing street name index ... " << std::flush;
|
||||||
std::string nameOutFileName = (outputFileName + ".names");
|
std::string nameOutFileName = (output_file_name + ".names");
|
||||||
ofstream nameOutFile(nameOutFileName.c_str(), ios::binary);
|
std::ofstream nameOutFile(nameOutFileName.c_str(), std::ios::binary);
|
||||||
unsigned sizeOfNameIndex = nameVector.size();
|
unsigned sizeOfNameIndex = nameVector.size();
|
||||||
nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
|
nameOutFile.write((char *)&(sizeOfNameIndex), sizeof(unsigned));
|
||||||
|
|
||||||
BOOST_FOREACH(string str, nameVector) {
|
BOOST_FOREACH(const std::string & str, nameVector) {
|
||||||
unsigned lengthOfRawString = strlen(str.c_str());
|
unsigned lengthOfRawString = strlen(str.c_str());
|
||||||
nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
|
nameOutFile.write((char *)&(lengthOfRawString), sizeof(unsigned));
|
||||||
nameOutFile.write(str.c_str(), lengthOfRawString);
|
nameOutFile.write(str.c_str(), lengthOfRawString);
|
||||||
}
|
}
|
||||||
|
|
||||||
nameOutFile.close();
|
nameOutFile.close();
|
||||||
cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl;
|
||||||
|
|
||||||
// time = get_timestamp();
|
// time = get_timestamp();
|
||||||
// cout << "[extractor] writing address list ... " << flush;
|
// cout << "[extractor] writing address list ... " << flush;
|
||||||
@@ -295,11 +298,11 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
// addressOutFile.close();
|
// addressOutFile.close();
|
||||||
// cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
// cout << "ok, after " << get_timestamp() - time << "s" << endl;
|
||||||
|
|
||||||
INFO("Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges");
|
SimpleLogger().Write() << "Processed " << usedNodeCounter << " nodes and " << usedEdgeCounter << " edges";
|
||||||
|
|
||||||
|
|
||||||
} catch ( const exception& e ) {
|
} catch ( const std::exception& e ) {
|
||||||
cerr << "Caught Execption:" << e.what() << endl;
|
std::cerr << "Caught Execption:" << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,31 +21,29 @@
|
|||||||
#ifndef EXTRACTIONCONTAINERS_H_
|
#ifndef EXTRACTIONCONTAINERS_H_
|
||||||
#define EXTRACTIONCONTAINERS_H_
|
#define EXTRACTIONCONTAINERS_H_
|
||||||
|
|
||||||
|
#include "ExtractorStructs.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/TimingUtil.h"
|
||||||
|
#include "../Util/UUID.h"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <stxxl.h>
|
#include <stxxl.h>
|
||||||
|
|
||||||
#include "ExtractorStructs.h"
|
|
||||||
#include "../DataStructures/Util.h"
|
|
||||||
|
|
||||||
class ExtractionContainers {
|
class ExtractionContainers {
|
||||||
public:
|
public:
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||||
typedef stxxl::vector<_Node> STXXLNodeVector;
|
typedef stxxl::vector<_Node> STXXLNodeVector;
|
||||||
typedef stxxl::vector<_Edge> 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<_RawRestrictionContainer> STXXLRestrictionsVector;
|
||||||
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector;
|
||||||
|
|
||||||
ExtractionContainers() {
|
ExtractionContainers() {
|
||||||
//Check if another instance of stxxl is already running or if there is a general problem
|
//Check if another instance of stxxl is already running or if there is a general problem
|
||||||
try {
|
stxxl::vector<unsigned> testForRunningInstance;
|
||||||
stxxl::vector<unsigned> testForRunningInstance;
|
|
||||||
} catch(std::exception & e) {
|
|
||||||
ERR("Could not instantiate STXXL layer." << std::endl << e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
nameVector.push_back("");
|
nameVector.push_back("");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ExtractionContainers() {
|
virtual ~ExtractionContainers() {
|
||||||
usedNodeIDs.clear();
|
usedNodeIDs.clear();
|
||||||
allNodes.clear();
|
allNodes.clear();
|
||||||
@@ -55,7 +53,7 @@ public:
|
|||||||
wayStartEndVector.clear();
|
wayStartEndVector.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrepareData( const std::string & outputFileName, const std::string restrictionsFileName, const unsigned amountOfRAM);
|
void PrepareData( const std::string & output_file_name, const std::string restrictionsFileName, const unsigned amountOfRAM);
|
||||||
|
|
||||||
STXXLNodeIDVector usedNodeIDs;
|
STXXLNodeIDVector usedNodeIDs;
|
||||||
STXXLNodeVector allNodes;
|
STXXLNodeVector allNodes;
|
||||||
@@ -63,7 +61,7 @@ public:
|
|||||||
STXXLStringVector nameVector;
|
STXXLStringVector nameVector;
|
||||||
STXXLRestrictionsVector restrictionsVector;
|
STXXLRestrictionsVector restrictionsVector;
|
||||||
STXXLWayIDStartEndVector wayStartEndVector;
|
STXXLWayIDStartEndVector wayStartEndVector;
|
||||||
|
const UUID uuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EXTRACTIONCONTAINERS_H_ */
|
#endif /* EXTRACTIONCONTAINERS_H_ */
|
||||||
|
|||||||
@@ -18,22 +18,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
|
#ifndef EXTRACTIONHELPERFUNCTIONS_H_
|
||||||
#define EXTRACTIONHELPERFUNCTIONS_H_
|
#define EXTRACTIONHELPERFUNCTIONS_H_
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string_regex.hpp>
|
#include <boost/algorithm/string_regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
namespace qi = boost::spirit::qi;
|
||||||
|
|
||||||
//TODO: Move into LUA
|
//TODO: Move into LUA
|
||||||
|
|
||||||
inline bool durationIsValid(const std::string &s) {
|
inline bool durationIsValid(const std::string &s) {
|
||||||
boost::regex e ("((\\d|\\d\\d):)*(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
||||||
|
|
||||||
std::vector< std::string > result;
|
std::vector< std::string > result;
|
||||||
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
|
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
|
||||||
@@ -42,17 +42,28 @@ inline bool durationIsValid(const std::string &s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned parseDuration(const std::string &s) {
|
inline unsigned parseDuration(const std::string &s) {
|
||||||
int hours = 0;
|
unsigned hours = 0;
|
||||||
int minutes = 0;
|
unsigned minutes = 0;
|
||||||
boost::regex e ("((\\d|\\d\\d):)*(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
unsigned seconds = 0;
|
||||||
|
boost::regex e ("((\\d|\\d\\d):(\\d|\\d\\d):(\\d|\\d\\d))|((\\d|\\d\\d):(\\d|\\d\\d))|(\\d|\\d\\d)",boost::regex_constants::icase|boost::regex_constants::perl);
|
||||||
|
|
||||||
std::vector< std::string > result;
|
std::vector< std::string > result;
|
||||||
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
|
boost::algorithm::split_regex( result, s, boost::regex( ":" ) ) ;
|
||||||
bool matched = regex_match(s, e);
|
bool matched = regex_match(s, e);
|
||||||
if(matched) {
|
if(matched) {
|
||||||
hours = (result.size()== 2) ? stringToInt(result[0]) : 0;
|
if(1 == result.size()) {
|
||||||
minutes = (result.size()== 2) ? stringToInt(result[1]) : stringToInt(result[0]);
|
minutes = stringToInt(result[0]);
|
||||||
return 600*(hours*60+minutes);
|
}
|
||||||
|
if(2 == result.size()) {
|
||||||
|
minutes = stringToInt(result[1]);
|
||||||
|
hours = stringToInt(result[0]);
|
||||||
|
}
|
||||||
|
if(3 == result.size()) {
|
||||||
|
seconds = stringToInt(result[2]);
|
||||||
|
minutes = stringToInt(result[1]);
|
||||||
|
hours = stringToInt(result[0]);
|
||||||
|
}
|
||||||
|
return 10*(3600*hours+60*minutes+seconds);
|
||||||
}
|
}
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
@@ -66,5 +77,4 @@ inline int parseMaxspeed(std::string input) { //call-by-value on purpose.
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
#endif /* EXTRACTIONHELPERFUNCTIONS_H_ */
|
||||||
|
|||||||
@@ -12,26 +12,6 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
@@ -40,7 +20,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
|
|
||||||
#include "ExtractorCallbacks.h"
|
#include "ExtractorCallbacks.h"
|
||||||
#include "ExtractionHelperFunctions.h"
|
|
||||||
|
|
||||||
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
||||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
||||||
@@ -48,58 +27,98 @@ ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * s
|
|||||||
stringMap = strMap;
|
stringMap = strMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractorCallbacks::~ExtractorCallbacks() {
|
ExtractorCallbacks::~ExtractorCallbacks() { }
|
||||||
}
|
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
bool ExtractorCallbacks::nodeFunction(_Node &n) {
|
void ExtractorCallbacks::nodeFunction(const _Node &n) {
|
||||||
if(n.lat <= 85*100000 && n.lat >= -85*100000)
|
if(n.lat <= 85*COORDINATE_PRECISION && n.lat >= -85*COORDINATE_PRECISION) {
|
||||||
externalMemory->allNodes.push_back(n);
|
externalMemory->allNodes.push_back(n);
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) {
|
bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) {
|
||||||
externalMemory->restrictionsVector.push_back(r);
|
externalMemory->restrictionsVector.push_back(r);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
bool ExtractorCallbacks::wayFunction(_Way &w) {
|
void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||||
/*** Store name of way and split it into edge segments ***/
|
if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile
|
||||||
|
if(UINT_MAX == parsed_way.id){
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"found bogus way with id: " << parsed_way.id <<
|
||||||
|
" of size " << parsed_way.path.size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( w.speed > 0 ) { //Only true if the way is specified by the speed profile
|
if(0 < parsed_way.duration) {
|
||||||
|
//TODO: iterate all way segments and set duration corresponding to the length of each segment
|
||||||
|
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"found way with bogus speed, id: " << parsed_way.id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//Get the unique identifier for the street name
|
//Get the unique identifier for the street name
|
||||||
const StringMap::const_iterator strit = stringMap->find(w.name);
|
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
|
||||||
if(strit == stringMap->end()) {
|
if(stringMap->end() == string_map_iterator) {
|
||||||
w.nameID = externalMemory->nameVector.size();
|
parsed_way.nameID = externalMemory->nameVector.size();
|
||||||
externalMemory->nameVector.push_back(w.name);
|
externalMemory->nameVector.push_back(parsed_way.name);
|
||||||
stringMap->insert(StringMap::value_type(w.name, w.nameID));
|
stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||||
} else {
|
} else {
|
||||||
w.nameID = strit->second;
|
parsed_way.nameID = string_map_iterator->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fabs(-1. - w.speed) < FLT_EPSILON){
|
if(ExtractionWay::opposite == parsed_way.direction) {
|
||||||
WARN("found way with bogus speed, id: " << w.id);
|
std::reverse( parsed_way.path.begin(), parsed_way.path.end() );
|
||||||
return true;
|
parsed_way.direction = ExtractionWay::oneway;
|
||||||
}
|
|
||||||
if(w.id == UINT_MAX) {
|
|
||||||
WARN("found way with unknown type: " << w.id);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( w.direction == _Way::opposite ){
|
const bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||||
std::reverse( w.path.begin(), w.path.end() );
|
|
||||||
}
|
|
||||||
|
|
||||||
for(vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) {
|
for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) {
|
||||||
externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, w.isDurationSet, w.isAccessRestricted));
|
externalMemory->allEdges.push_back(
|
||||||
externalMemory->usedNodeIDs.push_back(w.path[n]);
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
|
parsed_way.path[n+1],
|
||||||
|
parsed_way.type,
|
||||||
|
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||||
|
parsed_way.speed,
|
||||||
|
parsed_way.nameID,
|
||||||
|
parsed_way.roundabout,
|
||||||
|
parsed_way.ignoreInGrid,
|
||||||
|
(0 < parsed_way.duration),
|
||||||
|
parsed_way.isAccessRestricted
|
||||||
|
)
|
||||||
|
);
|
||||||
|
externalMemory->usedNodeIDs.push_back(parsed_way.path[n]);
|
||||||
}
|
}
|
||||||
externalMemory->usedNodeIDs.push_back(w.path.back());
|
externalMemory->usedNodeIDs.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(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1]));
|
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()));
|
||||||
|
|
||||||
|
if(split_bidirectional_edge) { //Only true if the way should be split
|
||||||
|
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) {
|
||||||
|
externalMemory->allEdges.push_back(
|
||||||
|
InternalExtractorEdge(parsed_way.path[n],
|
||||||
|
parsed_way.path[n+1],
|
||||||
|
parsed_way.type,
|
||||||
|
ExtractionWay::oneway,
|
||||||
|
parsed_way.backward_speed,
|
||||||
|
parsed_way.nameID,
|
||||||
|
parsed_way.roundabout,
|
||||||
|
parsed_way.ignoreInGrid,
|
||||||
|
(0 < parsed_way.duration),
|
||||||
|
parsed_way.isAccessRestricted,
|
||||||
|
(ExtractionWay::oneway == parsed_way.direction)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef EXTRACTORCALLBACKS_H_
|
#ifndef EXTRACTORCALLBACKS_H_
|
||||||
#define EXTRACTORCALLBACKS_H_
|
#define EXTRACTORCALLBACKS_H_
|
||||||
|
|
||||||
#include <string>
|
#include "ExtractionContainers.h"
|
||||||
#include <vector>
|
#include "ExtractionHelperFunctions.h"
|
||||||
|
#include "ExtractorStructs.h"
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
|
|
||||||
@@ -30,8 +33,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/algorithm/string/regex.hpp>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include "ExtractionContainers.h"
|
#include <string>
|
||||||
#include "ExtractorStructs.h"
|
#include <vector>
|
||||||
|
|
||||||
class ExtractorCallbacks{
|
class ExtractorCallbacks{
|
||||||
private:
|
private:
|
||||||
@@ -45,12 +48,12 @@ public:
|
|||||||
~ExtractorCallbacks();
|
~ExtractorCallbacks();
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
bool nodeFunction(_Node &n);
|
void nodeFunction(const _Node &n);
|
||||||
|
|
||||||
bool restrictionFunction(_RawRestrictionContainer &r);
|
bool restrictionFunction(const _RawRestrictionContainer &r);
|
||||||
|
|
||||||
/** warning: caller needs to take care of synchronization! */
|
/** warning: caller needs to take care of synchronization! */
|
||||||
bool wayFunction(_Way &w);
|
void wayFunction(ExtractionWay &w);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,75 +21,80 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef EXTRACTORSTRUCTS_H_
|
#ifndef EXTRACTORSTRUCTS_H_
|
||||||
#define EXTRACTORSTRUCTS_H_
|
#define EXTRACTORSTRUCTS_H_
|
||||||
|
|
||||||
#include <climits>
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include <string>
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
|
#include "../DataStructures/QueryNode.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/algorithm/string/regex.hpp>
|
#include <boost/algorithm/string/regex.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include <climits>
|
||||||
#include "../DataStructures/HashTable.h"
|
#include <string>
|
||||||
#include "../DataStructures/ImportNode.h"
|
|
||||||
#include "../DataStructures/NodeCoords.h"
|
|
||||||
#include "../DataStructures/Restriction.h"
|
|
||||||
#include "../DataStructures/Util.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
||||||
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
||||||
|
|
||||||
struct _Way {
|
struct ExtractionWay {
|
||||||
_Way() {
|
ExtractionWay() {
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Clear(){
|
inline void Clear(){
|
||||||
id = UINT_MAX;
|
id = UINT_MAX;
|
||||||
nameID = UINT_MAX;
|
nameID = UINT_MAX;
|
||||||
path.clear();
|
path.clear();
|
||||||
keyVals.EraseAll();
|
keyVals.clear();
|
||||||
direction = _Way::notSure;
|
direction = ExtractionWay::notSure;
|
||||||
speed = -1;
|
speed = -1;
|
||||||
|
backward_speed = -1;
|
||||||
|
duration = -1;
|
||||||
type = -1;
|
type = -1;
|
||||||
access = true;
|
access = true;
|
||||||
roundabout = false;
|
roundabout = false;
|
||||||
isDurationSet = false;
|
|
||||||
isAccessRestricted = false;
|
isAccessRestricted = false;
|
||||||
ignoreInGrid = false;
|
ignoreInGrid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum Directions {
|
||||||
notSure = 0, oneway, bidirectional, opposite
|
notSure = 0, oneway, bidirectional, opposite
|
||||||
} direction;
|
};
|
||||||
|
Directions direction;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
std::string name;
|
std::string name;
|
||||||
double speed;
|
double speed;
|
||||||
|
double backward_speed;
|
||||||
|
double duration;
|
||||||
short type;
|
short type;
|
||||||
bool access;
|
bool access;
|
||||||
bool roundabout;
|
bool roundabout;
|
||||||
bool isDurationSet;
|
|
||||||
bool isAccessRestricted;
|
bool isAccessRestricted;
|
||||||
bool ignoreInGrid;
|
bool ignoreInGrid;
|
||||||
std::vector< NodeID > path;
|
std::vector< NodeID > path;
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Relation {
|
struct ExtractorRelation {
|
||||||
_Relation() : type(unknown){}
|
ExtractorRelation() : type(unknown){}
|
||||||
enum {
|
enum {
|
||||||
unknown = 0, ferry, turnRestriction
|
unknown = 0, ferry, turnRestriction
|
||||||
} type;
|
} type;
|
||||||
HashTable<std::string, std::string> keyVals;
|
HashTable<std::string, std::string> keyVals;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Edge {
|
struct InternalExtractorEdge {
|
||||||
_Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {};
|
InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {};
|
||||||
_Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { }
|
InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
|
||||||
_Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { }
|
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { }
|
||||||
_Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) {
|
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) {
|
||||||
|
assert(0 <= type);
|
||||||
|
}
|
||||||
|
InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) {
|
||||||
assert(0 <= type);
|
assert(0 <= type);
|
||||||
}
|
}
|
||||||
NodeID start;
|
NodeID start;
|
||||||
@@ -102,19 +107,21 @@ struct _Edge {
|
|||||||
bool ignoreInGrid;
|
bool ignoreInGrid;
|
||||||
bool isDurationSet;
|
bool isDurationSet;
|
||||||
bool isAccessRestricted;
|
bool isAccessRestricted;
|
||||||
|
bool isContraFlow;
|
||||||
|
|
||||||
_Coordinate startCoord;
|
FixedPointCoordinate startCoord;
|
||||||
_Coordinate targetCoord;
|
FixedPointCoordinate targetCoord;
|
||||||
|
|
||||||
static _Edge min_value() {
|
static InternalExtractorEdge min_value() {
|
||||||
return _Edge(0,0);
|
return InternalExtractorEdge(0,0);
|
||||||
}
|
}
|
||||||
static _Edge max_value() {
|
static InternalExtractorEdge max_value() {
|
||||||
return _Edge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
|
return InternalExtractorEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct _WayIDStartAndEndEdge {
|
struct _WayIDStartAndEndEdge {
|
||||||
unsigned wayID;
|
unsigned wayID;
|
||||||
NodeID firstStart;
|
NodeID firstStart;
|
||||||
@@ -125,10 +132,10 @@ struct _WayIDStartAndEndEdge {
|
|||||||
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
|
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
|
||||||
|
|
||||||
static _WayIDStartAndEndEdge min_value() {
|
static _WayIDStartAndEndEdge min_value() {
|
||||||
return _WayIDStartAndEndEdge((numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)());
|
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
|
||||||
}
|
}
|
||||||
static _WayIDStartAndEndEdge max_value() {
|
static _WayIDStartAndEndEdge max_value() {
|
||||||
return _WayIDStartAndEndEdge((numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)(), (numeric_limits<unsigned>::max)());
|
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -171,38 +178,33 @@ struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpEdgeByStartID : public std::binary_function<_Edge, _Edge, bool>
|
struct CmpEdgeByStartID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
|
||||||
{
|
typedef InternalExtractorEdge value_type;
|
||||||
typedef _Edge value_type;
|
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
|
||||||
bool operator () (const _Edge & a, const _Edge & b) const {
|
|
||||||
return a.start < b.start;
|
return a.start < b.start;
|
||||||
}
|
}
|
||||||
value_type max_value() {
|
value_type max_value() {
|
||||||
return _Edge::max_value();
|
return InternalExtractorEdge::max_value();
|
||||||
}
|
}
|
||||||
value_type min_value() {
|
value_type min_value() {
|
||||||
return _Edge::min_value();
|
return InternalExtractorEdge::min_value();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool>
|
struct CmpEdgeByTargetID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
|
||||||
{
|
typedef InternalExtractorEdge value_type;
|
||||||
typedef _Edge value_type;
|
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
|
||||||
bool operator () (const _Edge & a, const _Edge & b) const
|
|
||||||
{
|
|
||||||
return a.target < b.target;
|
return a.target < b.target;
|
||||||
}
|
}
|
||||||
value_type max_value()
|
value_type max_value() {
|
||||||
{
|
return InternalExtractorEdge::max_value();
|
||||||
return _Edge::max_value();
|
|
||||||
}
|
}
|
||||||
value_type min_value()
|
value_type min_value() {
|
||||||
{
|
return InternalExtractorEdge::min_value();
|
||||||
return _Edge::min_value();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline string GetRandomString() {
|
inline std::string GetRandomString() {
|
||||||
char s[128];
|
char s[128];
|
||||||
static const char alphanum[] =
|
static const char alphanum[] =
|
||||||
"0123456789"
|
"0123456789"
|
||||||
@@ -213,7 +215,7 @@ inline string GetRandomString() {
|
|||||||
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
|
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||||
}
|
}
|
||||||
s[127] = 0;
|
s[127] = 0;
|
||||||
return string(s);
|
return std::string(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* EXTRACTORSTRUCTS_H_ */
|
#endif /* EXTRACTORSTRUCTS_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,487 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PBFParser.h"
|
||||||
|
|
||||||
|
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
|
||||||
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
|
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
||||||
|
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
||||||
|
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
|
||||||
|
input.open(fileName, std::ios::in | std::ios::binary);
|
||||||
|
|
||||||
|
if (!input) {
|
||||||
|
throw OSRMException("pbf file not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
blockCount = 0;
|
||||||
|
groupCount = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
PBFParser::~PBFParser() {
|
||||||
|
if(input.is_open()) {
|
||||||
|
input.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up any leftover ThreadData objects in the queue
|
||||||
|
_ThreadData* td;
|
||||||
|
while (threadDataQueue->try_pop(td)) {
|
||||||
|
delete td;
|
||||||
|
}
|
||||||
|
google::protobuf::ShutdownProtobufLibrary();
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
|
"parsed " << blockCount <<
|
||||||
|
" blocks from pbf with " << groupCount <<
|
||||||
|
" groups";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PBFParser::ReadHeader() {
|
||||||
|
_ThreadData initData;
|
||||||
|
/** read Header */
|
||||||
|
if(!readPBFBlobHeader(input, &initData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(readBlob(input, &initData)) {
|
||||||
|
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
|
||||||
|
std::cerr << "[error] Header not parseable!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
|
||||||
|
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
|
||||||
|
bool supported = false;
|
||||||
|
if ( "OsmSchema-V0.6" == feature ) {
|
||||||
|
supported = true;
|
||||||
|
}
|
||||||
|
else if ( "DenseNodes" == feature ) {
|
||||||
|
supported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !supported ) {
|
||||||
|
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "[error] blob not loaded!" << std::endl;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::ReadData() {
|
||||||
|
bool keepRunning = true;
|
||||||
|
do {
|
||||||
|
_ThreadData *threadData = new _ThreadData();
|
||||||
|
keepRunning = readNextBlock(input, threadData);
|
||||||
|
|
||||||
|
if (keepRunning) {
|
||||||
|
threadDataQueue->push(threadData);
|
||||||
|
} else {
|
||||||
|
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
|
||||||
|
delete threadData;
|
||||||
|
}
|
||||||
|
} while(keepRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::ParseData() {
|
||||||
|
while (true) {
|
||||||
|
_ThreadData *threadData;
|
||||||
|
threadDataQueue->wait_and_pop(threadData);
|
||||||
|
if( NULL==threadData ) {
|
||||||
|
SimpleLogger().Write() << "Parse Data Thread Finished";
|
||||||
|
threadDataQueue->push(NULL); // Signal end of data for other threads
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadBlock(threadData);
|
||||||
|
|
||||||
|
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
|
||||||
|
threadData->currentGroupID = i;
|
||||||
|
loadGroup(threadData);
|
||||||
|
|
||||||
|
if(threadData->entityTypeIndicator == TypeNode) {
|
||||||
|
parseNode(threadData);
|
||||||
|
}
|
||||||
|
if(threadData->entityTypeIndicator == TypeWay) {
|
||||||
|
parseWay(threadData);
|
||||||
|
}
|
||||||
|
if(threadData->entityTypeIndicator == TypeRelation) {
|
||||||
|
parseRelation(threadData);
|
||||||
|
}
|
||||||
|
if(threadData->entityTypeIndicator == TypeDenseNode) {
|
||||||
|
parseDenseNode(threadData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete threadData;
|
||||||
|
threadData = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PBFParser::Parse() {
|
||||||
|
// Start the read and parse threads
|
||||||
|
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
|
||||||
|
|
||||||
|
//Open several parse threads that are synchronized before call to
|
||||||
|
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
|
||||||
|
|
||||||
|
// Wait for the threads to finish
|
||||||
|
readThread.join();
|
||||||
|
parseThread.join();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||||
|
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
|
||||||
|
int denseTagIndex = 0;
|
||||||
|
int64_t m_lastDenseID = 0;
|
||||||
|
int64_t m_lastDenseLatitude = 0;
|
||||||
|
int64_t m_lastDenseLongitude = 0;
|
||||||
|
|
||||||
|
const int number_of_nodes = dense.id_size();
|
||||||
|
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
|
||||||
|
for(int i = 0; i < number_of_nodes; ++i) {
|
||||||
|
m_lastDenseID += dense.id( i );
|
||||||
|
m_lastDenseLatitude += dense.lat( i );
|
||||||
|
m_lastDenseLongitude += dense.lon( i );
|
||||||
|
extracted_nodes_vector[i].id = m_lastDenseID;
|
||||||
|
extracted_nodes_vector[i].lat = COORDINATE_PRECISION*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
|
||||||
|
extracted_nodes_vector[i].lon = COORDINATE_PRECISION*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
||||||
|
while (denseTagIndex < dense.keys_vals_size()) {
|
||||||
|
const int tagValue = dense.keys_vals( denseTagIndex );
|
||||||
|
if( 0==tagValue ) {
|
||||||
|
++denseTagIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
|
||||||
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
|
||||||
|
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
|
||||||
|
extracted_nodes_vector[i].keyVals.insert(std::make_pair(key, value));
|
||||||
|
denseTagIndex += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma omp parallel for schedule ( guided )
|
||||||
|
for(int i = 0; i < number_of_nodes; ++i) {
|
||||||
|
ImportNode &n = extracted_nodes_vector[i];
|
||||||
|
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(ImportNode &n, extracted_nodes_vector) {
|
||||||
|
extractor_callbacks->nodeFunction(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::parseNode(_ThreadData * ) {
|
||||||
|
throw OSRMException(
|
||||||
|
"Parsing of simple nodes not supported. PBF should use dense nodes"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||||
|
//TODO: leave early, if relation is not a restriction
|
||||||
|
//TODO: reuse rawRestriction container
|
||||||
|
if( !use_turn_restrictions ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
||||||
|
for(int i = 0; i < group.relations_size(); ++i ) {
|
||||||
|
std::string except_tag_string;
|
||||||
|
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
|
||||||
|
bool isRestriction = false;
|
||||||
|
bool isOnlyRestriction = false;
|
||||||
|
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
|
||||||
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
|
||||||
|
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
|
||||||
|
if ("type" == key) {
|
||||||
|
if( "restriction" == val) {
|
||||||
|
isRestriction = true;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("restriction" == key) {
|
||||||
|
if(val.find("only_") == 0) {
|
||||||
|
isOnlyRestriction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("except" == key) {
|
||||||
|
except_tag_string = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isRestriction && ShouldIgnoreRestriction(except_tag_string) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isRestriction) {
|
||||||
|
int64_t lastRef = 0;
|
||||||
|
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
||||||
|
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
|
||||||
|
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
|
||||||
|
lastRef += inputRelation.memids(rolesIndex);
|
||||||
|
|
||||||
|
if(!("from" == role || "to" == role || "via" == role)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(inputRelation.types(rolesIndex)) {
|
||||||
|
case 0: //node
|
||||||
|
if("from" == role || "to" == role) { //Only via should be a node
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assert("via" == role);
|
||||||
|
if(UINT_MAX != currentRestrictionContainer.viaNode) {
|
||||||
|
currentRestrictionContainer.viaNode = UINT_MAX;
|
||||||
|
}
|
||||||
|
assert(UINT_MAX == currentRestrictionContainer.viaNode);
|
||||||
|
currentRestrictionContainer.restriction.viaNode = lastRef;
|
||||||
|
break;
|
||||||
|
case 1: //way
|
||||||
|
assert("from" == role || "to" == role || "via" == role);
|
||||||
|
if("from" == role) {
|
||||||
|
currentRestrictionContainer.fromWay = lastRef;
|
||||||
|
}
|
||||||
|
if ("to" == role) {
|
||||||
|
currentRestrictionContainer.toWay = lastRef;
|
||||||
|
}
|
||||||
|
if ("via" == role) {
|
||||||
|
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
|
||||||
|
currentRestrictionContainer.viaNode = lastRef;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: //relation, not used. relations relating to relations are evil.
|
||||||
|
continue;
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: //should not happen
|
||||||
|
//cout << "unknown";
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!extractor_callbacks->restrictionFunction(currentRestrictionContainer)) {
|
||||||
|
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::parseWay(_ThreadData * threadData) {
|
||||||
|
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
|
||||||
|
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
||||||
|
for(int i = 0; i < number_of_ways; ++i) {
|
||||||
|
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
|
||||||
|
parsed_way_vector[i].id = inputWay.id();
|
||||||
|
unsigned pathNode(0);
|
||||||
|
const int number_of_referenced_nodes = inputWay.refs_size();
|
||||||
|
for(int j = 0; j < number_of_referenced_nodes; ++j) {
|
||||||
|
pathNode += inputWay.refs(j);
|
||||||
|
parsed_way_vector[i].path.push_back(pathNode);
|
||||||
|
}
|
||||||
|
assert(inputWay.keys_size() == inputWay.vals_size());
|
||||||
|
const int number_of_keys = inputWay.keys_size();
|
||||||
|
for(int j = 0; j < number_of_keys; ++j) {
|
||||||
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
|
||||||
|
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
|
||||||
|
parsed_way_vector[i].keyVals.insert(std::make_pair(key, val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma omp parallel for schedule ( guided )
|
||||||
|
for(int i = 0; i < number_of_ways; ++i) {
|
||||||
|
ExtractionWay & w = parsed_way_vector[i];
|
||||||
|
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
|
||||||
|
extractor_callbacks->wayFunction(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::loadGroup(_ThreadData * threadData) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
++groupCount;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
||||||
|
threadData->entityTypeIndicator = 0;
|
||||||
|
if ( group.nodes_size() != 0 ) {
|
||||||
|
threadData->entityTypeIndicator = TypeNode;
|
||||||
|
}
|
||||||
|
if ( group.ways_size() != 0 ) {
|
||||||
|
threadData->entityTypeIndicator = TypeWay;
|
||||||
|
}
|
||||||
|
if ( group.relations_size() != 0 ) {
|
||||||
|
threadData->entityTypeIndicator = TypeRelation;
|
||||||
|
}
|
||||||
|
if ( group.has_dense() ) {
|
||||||
|
threadData->entityTypeIndicator = TypeDenseNode;
|
||||||
|
assert( group.dense().id_size() != 0 );
|
||||||
|
}
|
||||||
|
assert( threadData->entityTypeIndicator != 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PBFParser::loadBlock(_ThreadData * threadData) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
++blockCount;
|
||||||
|
#endif
|
||||||
|
threadData->currentGroupID = 0;
|
||||||
|
threadData->currentEntityID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
|
||||||
|
int size(0);
|
||||||
|
stream.read((char *)&size, sizeof(int));
|
||||||
|
size = swapEndian(size);
|
||||||
|
if(stream.eof()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *data = new char[size];
|
||||||
|
stream.read(data, size*sizeof(data[0]));
|
||||||
|
|
||||||
|
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
|
||||||
|
delete[] data;
|
||||||
|
return dataSuccessfullyParsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
|
||||||
|
unsigned rawSize = threadData->PBFBlob.raw_size();
|
||||||
|
char* unpackedDataArray = new char[rawSize];
|
||||||
|
z_stream compressedDataStream;
|
||||||
|
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
|
||||||
|
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
|
||||||
|
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
|
||||||
|
compressedDataStream.avail_out = rawSize;
|
||||||
|
compressedDataStream.zalloc = Z_NULL;
|
||||||
|
compressedDataStream.zfree = Z_NULL;
|
||||||
|
compressedDataStream.opaque = Z_NULL;
|
||||||
|
int ret = inflateInit( &compressedDataStream );
|
||||||
|
if ( ret != Z_OK ) {
|
||||||
|
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
||||||
|
delete[] unpackedDataArray;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = inflate( &compressedDataStream, Z_FINISH );
|
||||||
|
if ( ret != Z_STREAM_END ) {
|
||||||
|
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
||||||
|
std::cerr << "[error] Error type: " << ret << std::endl;
|
||||||
|
delete[] unpackedDataArray;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = inflateEnd( &compressedDataStream );
|
||||||
|
if ( ret != Z_OK ) {
|
||||||
|
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
||||||
|
delete[] unpackedDataArray;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
|
||||||
|
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
|
||||||
|
delete[] unpackedDataArray;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
|
||||||
|
if(stream.eof()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int size = threadData->PBFBlobHeader.datasize();
|
||||||
|
if ( size < 0 || size > MAX_BLOB_SIZE ) {
|
||||||
|
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* data = new char[size];
|
||||||
|
stream.read(data, sizeof(data[0])*size);
|
||||||
|
|
||||||
|
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
|
||||||
|
std::cerr << "[error] failed to parse blob" << std::endl;
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( threadData->PBFBlob.has_raw() ) {
|
||||||
|
const std::string& data = threadData->PBFBlob.raw();
|
||||||
|
threadData->charBuffer.clear();
|
||||||
|
threadData->charBuffer.resize( data.size() );
|
||||||
|
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
|
||||||
|
} else if ( threadData->PBFBlob.has_zlib_data() ) {
|
||||||
|
if ( !unpackZLIB(stream, threadData) ) {
|
||||||
|
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if ( threadData->PBFBlob.has_lzma_data() ) {
|
||||||
|
if ( !unpackLZMA(stream, threadData) ) {
|
||||||
|
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
||||||
|
}
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
std::cerr << "[error] Blob contains no data" << std::endl;
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delete[] data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
|
||||||
|
if(stream.eof()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !readPBFBlobHeader(stream, threadData) ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !readBlob(stream, threadData) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
|
||||||
|
std::cerr << "failed to parse PrimitiveBlock" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
+46
-542
@@ -1,47 +1,47 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
open source routing machine
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PBFPARSER_H_
|
#ifndef PBFPARSER_H_
|
||||||
#define PBFPARSER_H_
|
#define PBFPARSER_H_
|
||||||
|
|
||||||
#include <zlib.h>
|
#include "BaseParser.h"
|
||||||
|
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/ConcurrentQueue.h"
|
||||||
|
#include "../Util/MachineInfo.h"
|
||||||
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include <osmpbf/fileformat.pb.h>
|
#include <osmpbf/fileformat.pb.h>
|
||||||
#include <osmpbf/osmformat.pb.h>
|
#include <osmpbf/osmformat.pb.h>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "BaseParser.h"
|
class PBFParser : public BaseParser {
|
||||||
#include "ExtractorCallbacks.h"
|
|
||||||
#include "ExtractorStructs.h"
|
|
||||||
#include "ScriptingEnvironment.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/ConcurrentQueue.h"
|
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
|
|
||||||
class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> {
|
|
||||||
|
|
||||||
// typedef BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> super;
|
|
||||||
|
|
||||||
enum EntityType {
|
enum EntityType {
|
||||||
TypeNode = 1,
|
TypeNode = 1,
|
||||||
@@ -50,11 +50,6 @@ class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionCo
|
|||||||
TypeDenseNode = 8
|
TypeDenseNode = 8
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
enum Endianness {
|
|
||||||
LittleEndian = 1,
|
|
||||||
BigEndian = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _ThreadData {
|
struct _ThreadData {
|
||||||
int currentGroupID;
|
int currentGroupID;
|
||||||
int currentEntityID;
|
int currentEntityID;
|
||||||
@@ -70,512 +65,27 @@ class PBFParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionCo
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PBFParser(const char * fileName) : externalMemory(NULL){
|
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
virtual ~PBFParser();
|
||||||
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
|
|
||||||
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
|
|
||||||
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
|
|
||||||
input.open(fileName, std::ios::in | std::ios::binary);
|
|
||||||
|
|
||||||
if (!input) {
|
inline bool ReadHeader();
|
||||||
std::cerr << fileName << ": File not found." << std::endl;
|
inline bool Parse();
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
blockCount = 0;
|
|
||||||
groupCount = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterCallbacks(ExtractorCallbacks * em) {
|
|
||||||
externalMemory = em;
|
|
||||||
}
|
|
||||||
|
|
||||||
//call by value, but who cares. It is done once.
|
|
||||||
void RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
|
|
||||||
scriptingEnvironment = _se;
|
|
||||||
}
|
|
||||||
|
|
||||||
~PBFParser() {
|
|
||||||
if(input.is_open())
|
|
||||||
input.close();
|
|
||||||
|
|
||||||
// Clean up any leftover ThreadData objects in the queue
|
|
||||||
_ThreadData* td;
|
|
||||||
while (threadDataQueue->try_pop(td)) {
|
|
||||||
delete td;
|
|
||||||
}
|
|
||||||
google::protobuf::ShutdownProtobufLibrary();
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Init() {
|
|
||||||
_ThreadData initData;
|
|
||||||
/** read Header */
|
|
||||||
if(!readPBFBlobHeader(input, &initData)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(readBlob(input, &initData)) {
|
|
||||||
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
|
|
||||||
std::cerr << "[error] Header not parseable!" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
|
|
||||||
const std::string& feature = initData.PBFHeaderBlock.required_features( i );
|
|
||||||
bool supported = false;
|
|
||||||
if ( "OsmSchema-V0.6" == feature )
|
|
||||||
supported = true;
|
|
||||||
else if ( "DenseNodes" == feature )
|
|
||||||
supported = true;
|
|
||||||
|
|
||||||
if ( !supported ) {
|
|
||||||
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cerr << "[error] blob not loaded!" << std::endl;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ReadData() {
|
|
||||||
bool keepRunning = true;
|
|
||||||
do {
|
|
||||||
_ThreadData *threadData = new _ThreadData();
|
|
||||||
keepRunning = readNextBlock(input, threadData);
|
|
||||||
|
|
||||||
if (keepRunning)
|
|
||||||
threadDataQueue->push(threadData);
|
|
||||||
else {
|
|
||||||
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
|
|
||||||
delete threadData;
|
|
||||||
}
|
|
||||||
} while(keepRunning);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ParseData() {
|
|
||||||
while (1) {
|
|
||||||
_ThreadData *threadData;
|
|
||||||
threadDataQueue->wait_and_pop(threadData);
|
|
||||||
if (threadData == NULL) {
|
|
||||||
INFO("Parse Data Thread Finished");
|
|
||||||
threadDataQueue->push(NULL); // Signal end of data for other threads
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadBlock(threadData);
|
|
||||||
|
|
||||||
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
|
|
||||||
threadData->currentGroupID = i;
|
|
||||||
loadGroup(threadData);
|
|
||||||
|
|
||||||
if(threadData->entityTypeIndicator == TypeNode)
|
|
||||||
parseNode(threadData);
|
|
||||||
if(threadData->entityTypeIndicator == TypeWay)
|
|
||||||
parseWay(threadData);
|
|
||||||
if(threadData->entityTypeIndicator == TypeRelation)
|
|
||||||
parseRelation(threadData);
|
|
||||||
if(threadData->entityTypeIndicator == TypeDenseNode)
|
|
||||||
parseDenseNode(threadData);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete threadData;
|
|
||||||
threadData = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool Parse() {
|
|
||||||
// Start the read and parse threads
|
|
||||||
boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
|
|
||||||
|
|
||||||
//Open several parse threads that are synchronized before call to
|
|
||||||
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
|
|
||||||
|
|
||||||
// Wait for the threads to finish
|
|
||||||
readThread.join();
|
|
||||||
parseThread.join();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
inline void ReadData();
|
||||||
|
inline void ParseData();
|
||||||
|
inline void parseDenseNode(_ThreadData * threadData);
|
||||||
|
inline void parseNode(_ThreadData * );
|
||||||
|
inline void parseRelation(_ThreadData * threadData);
|
||||||
|
inline void parseWay(_ThreadData * threadData);
|
||||||
|
|
||||||
inline void parseDenseNode(_ThreadData * threadData) {
|
inline void loadGroup(_ThreadData * threadData);
|
||||||
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
|
inline void loadBlock(_ThreadData * threadData);
|
||||||
int denseTagIndex = 0;
|
inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData);
|
||||||
int m_lastDenseID = 0;
|
inline bool unpackZLIB(std::fstream &, _ThreadData * threadData);
|
||||||
int m_lastDenseLatitude = 0;
|
inline bool unpackLZMA(std::fstream &, _ThreadData * );
|
||||||
int m_lastDenseLongitude = 0;
|
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ;
|
||||||
|
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData);
|
||||||
ImportNode n;
|
|
||||||
std::vector<ImportNode> nodesToParse;
|
|
||||||
for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) {
|
|
||||||
n.Clear();
|
|
||||||
m_lastDenseID += dense.id( i );
|
|
||||||
m_lastDenseLatitude += dense.lat( i );
|
|
||||||
m_lastDenseLongitude += dense.lon( i );
|
|
||||||
n.id = m_lastDenseID;
|
|
||||||
n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO;
|
|
||||||
n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
|
||||||
while (denseTagIndex < dense.keys_vals_size()) {
|
|
||||||
const int tagValue = dense.keys_vals( denseTagIndex );
|
|
||||||
if(tagValue == 0) {
|
|
||||||
++denseTagIndex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
|
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
|
|
||||||
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
|
|
||||||
n.keyVals.Add(key, value);
|
|
||||||
denseTagIndex += 2;
|
|
||||||
}
|
|
||||||
nodesToParse.push_back(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned endi_nodes = nodesToParse.size();
|
|
||||||
#pragma omp parallel for schedule ( guided )
|
|
||||||
for(unsigned i = 0; i < endi_nodes; ++i) {
|
|
||||||
ImportNode &n = nodesToParse[i];
|
|
||||||
/** Pass the unpacked node to the LUA call back **/
|
|
||||||
try {
|
|
||||||
luabind::call_function<int>(
|
|
||||||
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
|
|
||||||
"node_function",
|
|
||||||
boost::ref(n)
|
|
||||||
);
|
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
ERR(er.what());
|
|
||||||
}
|
|
||||||
// catch (...) {
|
|
||||||
// ERR("Unknown error occurred during PBF dense node parsing!");
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_FOREACH(ImportNode &n, nodesToParse) {
|
|
||||||
if(!externalMemory->nodeFunction(n))
|
|
||||||
std::cerr << "[PBFParser] dense node not parsed" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void parseNode(_ThreadData * ) {
|
|
||||||
ERR("Parsing of simple nodes not supported. PBF should use dense nodes");
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void parseRelation(_ThreadData * threadData) {
|
|
||||||
//TODO: leave early, if relatio is not a restriction
|
|
||||||
//TODO: reuse rawRestriction container
|
|
||||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
|
||||||
for(int i = 0; i < group.relations_size(); ++i ) {
|
|
||||||
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
|
|
||||||
bool isRestriction = false;
|
|
||||||
bool isOnlyRestriction = false;
|
|
||||||
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
|
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
|
|
||||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
|
|
||||||
if ("type" == key) {
|
|
||||||
if( "restriction" == val)
|
|
||||||
isRestriction = true;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ("restriction" == key) {
|
|
||||||
if(val.find("only_") == 0)
|
|
||||||
isOnlyRestriction = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if(isRestriction) {
|
|
||||||
long long lastRef = 0;
|
|
||||||
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
|
|
||||||
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
|
|
||||||
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
|
|
||||||
lastRef += inputRelation.memids(rolesIndex);
|
|
||||||
|
|
||||||
if(false == ("from" == role || "to" == role || "via" == role)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(inputRelation.types(rolesIndex)) {
|
|
||||||
case 0: //node
|
|
||||||
if("from" == role || "to" == role) //Only via should be a node
|
|
||||||
continue;
|
|
||||||
assert("via" == role);
|
|
||||||
if(UINT_MAX != currentRestrictionContainer.viaNode)
|
|
||||||
currentRestrictionContainer.viaNode = UINT_MAX;
|
|
||||||
assert(UINT_MAX == currentRestrictionContainer.viaNode);
|
|
||||||
currentRestrictionContainer.restriction.viaNode = lastRef;
|
|
||||||
break;
|
|
||||||
case 1: //way
|
|
||||||
assert("from" == role || "to" == role || "via" == role);
|
|
||||||
if("from" == role) {
|
|
||||||
currentRestrictionContainer.fromWay = lastRef;
|
|
||||||
}
|
|
||||||
if ("to" == role) {
|
|
||||||
currentRestrictionContainer.toWay = lastRef;
|
|
||||||
}
|
|
||||||
if ("via" == role) {
|
|
||||||
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
|
|
||||||
currentRestrictionContainer.viaNode = lastRef;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: //relation, not used. relations relating to relations are evil.
|
|
||||||
continue;
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: //should not happen
|
|
||||||
//cout << "unknown";
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if(UINT_MAX != currentRestriction.viaNode) {
|
|
||||||
// cout << "restr from " << currentRestriction.from << " via ";
|
|
||||||
// cout << "node " << currentRestriction.viaNode;
|
|
||||||
// cout << " to " << currentRestriction.to << endl;
|
|
||||||
// }
|
|
||||||
if(!externalMemory->restrictionFunction(currentRestrictionContainer))
|
|
||||||
std::cerr << "[PBFParser] relation not parsed" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void parseWay(_ThreadData * threadData) {
|
|
||||||
_Way w;
|
|
||||||
std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size());
|
|
||||||
for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) {
|
|
||||||
w.Clear();
|
|
||||||
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
|
|
||||||
w.id = inputWay.id();
|
|
||||||
unsigned pathNode(0);
|
|
||||||
for(int i = 0; i < inputWay.refs_size(); ++i) {
|
|
||||||
pathNode += inputWay.refs(i);
|
|
||||||
w.path.push_back(pathNode);
|
|
||||||
}
|
|
||||||
assert(inputWay.keys_size() == inputWay.vals_size());
|
|
||||||
for(int i = 0; i < inputWay.keys_size(); ++i) {
|
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i));
|
|
||||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i));
|
|
||||||
w.keyVals.Add(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
waysToParse.push_back(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned endi_ways = waysToParse.size();
|
|
||||||
#pragma omp parallel for schedule ( guided )
|
|
||||||
for(unsigned i = 0; i < endi_ways; ++i) {
|
|
||||||
_Way & w = waysToParse[i];
|
|
||||||
/** Pass the unpacked way to the LUA call back **/
|
|
||||||
try {
|
|
||||||
luabind::call_function<int>(
|
|
||||||
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
|
|
||||||
"way_function",
|
|
||||||
boost::ref(w),
|
|
||||||
w.path.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
ERR(er.what());
|
|
||||||
}
|
|
||||||
// catch (...) {
|
|
||||||
// ERR("Unknown error!");
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_FOREACH(_Way & w, waysToParse) {
|
|
||||||
if(!externalMemory->wayFunction(w)) {
|
|
||||||
std::cerr << "[PBFParser] way not parsed" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void loadGroup(_ThreadData * threadData) {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
++groupCount;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
|
|
||||||
threadData->entityTypeIndicator = 0;
|
|
||||||
if ( group.nodes_size() != 0 ) {
|
|
||||||
threadData->entityTypeIndicator = TypeNode;
|
|
||||||
}
|
|
||||||
if ( group.ways_size() != 0 ) {
|
|
||||||
threadData->entityTypeIndicator = TypeWay;
|
|
||||||
}
|
|
||||||
if ( group.relations_size() != 0 ) {
|
|
||||||
threadData->entityTypeIndicator = TypeRelation;
|
|
||||||
}
|
|
||||||
if ( group.has_dense() ) {
|
|
||||||
threadData->entityTypeIndicator = TypeDenseNode;
|
|
||||||
assert( group.dense().id_size() != 0 );
|
|
||||||
}
|
|
||||||
assert( threadData->entityTypeIndicator != 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void loadBlock(_ThreadData * threadData) {
|
|
||||||
#ifndef NDEBUG
|
|
||||||
++blockCount;
|
|
||||||
#endif
|
|
||||||
threadData->currentGroupID = 0;
|
|
||||||
threadData->currentEntityID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reverses Network Byte Order into something usable, compiles down to a bswap-mov combination */
|
|
||||||
inline unsigned swapEndian(unsigned x) const {
|
|
||||||
if(getMachineEndianness() == LittleEndian)
|
|
||||||
return ( (x>>24) | ((x<<8) & 0x00FF0000) | ((x>>8) & 0x0000FF00) | (x<<24) );
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
|
|
||||||
int size(0);
|
|
||||||
stream.read((char *)&size, sizeof(int));
|
|
||||||
size = swapEndian(size);
|
|
||||||
if(stream.eof()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
char *data = new char[size];
|
|
||||||
stream.read(data, size*sizeof(data[0]));
|
|
||||||
|
|
||||||
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
|
|
||||||
delete[] data;
|
|
||||||
return dataSuccessfullyParsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool unpackZLIB(std::fstream &, _ThreadData * threadData) {
|
|
||||||
unsigned rawSize = threadData->PBFBlob.raw_size();
|
|
||||||
char* unpackedDataArray = new char[rawSize];
|
|
||||||
z_stream compressedDataStream;
|
|
||||||
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
|
|
||||||
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
|
|
||||||
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
|
|
||||||
compressedDataStream.avail_out = rawSize;
|
|
||||||
compressedDataStream.zalloc = Z_NULL;
|
|
||||||
compressedDataStream.zfree = Z_NULL;
|
|
||||||
compressedDataStream.opaque = Z_NULL;
|
|
||||||
int ret = inflateInit( &compressedDataStream );
|
|
||||||
if ( ret != Z_OK ) {
|
|
||||||
std::cerr << "[error] failed to init zlib stream" << std::endl;
|
|
||||||
delete[] unpackedDataArray;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = inflate( &compressedDataStream, Z_FINISH );
|
|
||||||
if ( ret != Z_STREAM_END ) {
|
|
||||||
std::cerr << "[error] failed to inflate zlib stream" << std::endl;
|
|
||||||
std::cerr << "[error] Error type: " << ret << std::endl;
|
|
||||||
delete[] unpackedDataArray;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = inflateEnd( &compressedDataStream );
|
|
||||||
if ( ret != Z_OK ) {
|
|
||||||
std::cerr << "[error] failed to deinit zlib stream" << std::endl;
|
|
||||||
delete[] unpackedDataArray;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
|
|
||||||
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
|
|
||||||
delete[] unpackedDataArray;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool unpackLZMA(std::fstream &, _ThreadData * ) const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) {
|
|
||||||
if(stream.eof())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const int size = threadData->PBFBlobHeader.datasize();
|
|
||||||
if ( size < 0 || size > MAX_BLOB_SIZE ) {
|
|
||||||
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* data = new char[size];
|
|
||||||
stream.read(data, sizeof(data[0])*size);
|
|
||||||
|
|
||||||
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
|
|
||||||
std::cerr << "[error] failed to parse blob" << std::endl;
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( threadData->PBFBlob.has_raw() ) {
|
|
||||||
const std::string& data = threadData->PBFBlob.raw();
|
|
||||||
threadData->charBuffer.clear();
|
|
||||||
threadData->charBuffer.resize( data.size() );
|
|
||||||
std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
|
|
||||||
} else if ( threadData->PBFBlob.has_zlib_data() ) {
|
|
||||||
if ( !unpackZLIB(stream, threadData) ) {
|
|
||||||
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if ( threadData->PBFBlob.has_lzma_data() ) {
|
|
||||||
if ( !unpackLZMA(stream, threadData) )
|
|
||||||
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
std::cerr << "[error] Blob contains no data" << std::endl;
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
delete[] data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData) {
|
|
||||||
if(stream.eof()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !readPBFBlobHeader(stream, threadData) ){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !readBlob(stream, threadData) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
|
|
||||||
ERR("failed to parse PrimitiveBlock");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Is optimized to a single 'mov eax,1' on GCC, clang and icc using -O3
|
|
||||||
inline Endianness getMachineEndianness() const {
|
|
||||||
int i(1);
|
|
||||||
char *p = (char *) &i;
|
|
||||||
if (1 == p[0])
|
|
||||||
return LittleEndian;
|
|
||||||
return BigEndian;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int NANO = 1000 * 1000 * 1000;
|
static const int NANO = 1000 * 1000 * 1000;
|
||||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||||
@@ -586,15 +96,9 @@ private:
|
|||||||
unsigned groupCount;
|
unsigned groupCount;
|
||||||
unsigned blockCount;
|
unsigned blockCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExtractorCallbacks * externalMemory;
|
|
||||||
/* the input stream to parse */
|
|
||||||
std::fstream input;
|
|
||||||
|
|
||||||
/* ThreadData Queue */
|
std::fstream input; // the input stream to parse
|
||||||
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
||||||
|
|
||||||
ScriptingEnvironment scriptingEnvironment;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PBFPARSER_H_ */
|
#endif /* PBFPARSER_H_ */
|
||||||
|
|||||||
@@ -18,23 +18,16 @@
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "ScriptingEnvironment.h"
|
#include "ScriptingEnvironment.h"
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
|
|
||||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||||
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||||
INFO("Using script " << fileName);
|
SimpleLogger().Write() << "Using script " << fileName;
|
||||||
|
|
||||||
// Create a new lua state
|
// Create a new lua state
|
||||||
for(int i = 0; i < omp_get_max_threads(); ++i)
|
for(int i = 0; i < omp_get_max_threads(); ++i) {
|
||||||
luaStateVector.push_back(luaL_newstate());
|
luaStateVector.push_back(luaL_newstate());
|
||||||
|
}
|
||||||
|
|
||||||
// Connect LuaBind to this lua state for all threads
|
// Connect LuaBind to this lua state for all threads
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
@@ -44,69 +37,63 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
|||||||
//open utility libraries string library;
|
//open utility libraries string library;
|
||||||
luaL_openlibs(myLuaState);
|
luaL_openlibs(myLuaState);
|
||||||
|
|
||||||
|
luaAddScriptFolderToLoadPath( myLuaState, fileName );
|
||||||
|
|
||||||
// Add our function to the state's global scope
|
// Add our function to the state's global scope
|
||||||
luabind::module(myLuaState) [
|
luabind::module(myLuaState) [
|
||||||
luabind::def("print", LUA_print<std::string>),
|
luabind::def("print", LUA_print<std::string>),
|
||||||
luabind::def("parseMaxspeed", parseMaxspeed),
|
luabind::def("parseMaxspeed", parseMaxspeed),
|
||||||
luabind::def("durationIsValid", durationIsValid),
|
luabind::def("durationIsValid", durationIsValid),
|
||||||
luabind::def("parseDuration", parseDuration)
|
luabind::def("parseDuration", parseDuration)
|
||||||
];
|
];
|
||||||
//#pragma omp critical
|
|
||||||
// {
|
luabind::module(myLuaState) [
|
||||||
// if(0 != luaL_dostring(
|
luabind::class_<HashTable<std::string, std::string> >("keyVals")
|
||||||
// myLuaState,
|
.def("Add", &HashTable<std::string, std::string>::Add)
|
||||||
// "print('Initializing LUA engine')\n"
|
.def("Find", &HashTable<std::string, std::string>::Find)
|
||||||
// )) {
|
.def("Holds", &HashTable<std::string, std::string>::Holds)
|
||||||
// ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
];
|
||||||
// }
|
|
||||||
// }
|
luabind::module(myLuaState) [
|
||||||
luabind::module(myLuaState) [
|
luabind::class_<ImportNode>("Node")
|
||||||
luabind::class_<HashTable<std::string, std::string> >("keyVals")
|
.def(luabind::constructor<>())
|
||||||
.def("Add", &HashTable<std::string, std::string>::Add)
|
.def_readwrite("lat", &ImportNode::lat)
|
||||||
.def("Find", &HashTable<std::string, std::string>::Find)
|
.def_readwrite("lon", &ImportNode::lon)
|
||||||
.def("Holds", &HashTable<std::string, std::string>::Holds)
|
.def_readwrite("id", &ImportNode::id)
|
||||||
];
|
.def_readwrite("bollard", &ImportNode::bollard)
|
||||||
|
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
||||||
luabind::module(myLuaState) [
|
.def_readwrite("tags", &ImportNode::keyVals)
|
||||||
luabind::class_<ImportNode>("Node")
|
];
|
||||||
.def(luabind::constructor<>())
|
|
||||||
.def_readwrite("lat", &ImportNode::lat)
|
luabind::module(myLuaState) [
|
||||||
.def_readwrite("lon", &ImportNode::lon)
|
luabind::class_<ExtractionWay>("Way")
|
||||||
.def_readwrite("id", &ImportNode::id)
|
.def(luabind::constructor<>())
|
||||||
.def_readwrite("bollard", &ImportNode::bollard)
|
.def_readwrite("name", &ExtractionWay::name)
|
||||||
.def_readwrite("traffic_light", &ImportNode::trafficLight)
|
.def_readwrite("speed", &ExtractionWay::speed)
|
||||||
.def_readwrite("tags", &ImportNode::keyVals)
|
.def_readwrite("backward_speed", &ExtractionWay::backward_speed)
|
||||||
];
|
.def_readwrite("duration", &ExtractionWay::duration)
|
||||||
|
.def_readwrite("type", &ExtractionWay::type)
|
||||||
luabind::module(myLuaState) [
|
.def_readwrite("access", &ExtractionWay::access)
|
||||||
luabind::class_<_Way>("Way")
|
.def_readwrite("roundabout", &ExtractionWay::roundabout)
|
||||||
.def(luabind::constructor<>())
|
.def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted)
|
||||||
.def_readwrite("name", &_Way::name)
|
.def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid)
|
||||||
.def_readwrite("speed", &_Way::speed)
|
.def_readwrite("tags", &ExtractionWay::keyVals)
|
||||||
.def_readwrite("type", &_Way::type)
|
.def_readwrite("direction", &ExtractionWay::direction)
|
||||||
.def_readwrite("access", &_Way::access)
|
.enum_("constants") [
|
||||||
.def_readwrite("roundabout", &_Way::roundabout)
|
luabind::value("notSure", 0),
|
||||||
.def_readwrite("is_duration_set", &_Way::isDurationSet)
|
luabind::value("oneway", 1),
|
||||||
.def_readwrite("is_access_restricted", &_Way::isAccessRestricted)
|
luabind::value("bidirectional", 2),
|
||||||
.def_readwrite("ignore_in_grid", &_Way::ignoreInGrid)
|
luabind::value("opposite", 3)
|
||||||
.def_readwrite("tags", &_Way::keyVals)
|
]
|
||||||
.def_readwrite("direction", &_Way::direction)
|
];
|
||||||
.enum_("constants")
|
|
||||||
[
|
luabind::module(myLuaState) [
|
||||||
luabind::value("notSure", 0),
|
luabind::class_<std::vector<std::string> >("vector")
|
||||||
luabind::value("oneway", 1),
|
.def("Add", &std::vector<std::string>::push_back)
|
||||||
luabind::value("bidirectional", 2),
|
|
||||||
luabind::value("opposite", 3)
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Now call our function in a lua script
|
|
||||||
//#pragma omp critical
|
|
||||||
// {
|
|
||||||
// INFO("Parsing speedprofile from " << fileName );
|
|
||||||
// }
|
|
||||||
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
if(0 != luaL_dofile(myLuaState, fileName) ) {
|
||||||
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
throw OSRMException("ERROR occured in scripting block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,18 +21,16 @@
|
|||||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||||
#define SCRIPTINGENVIRONMENT_H_
|
#define SCRIPTINGENVIRONMENT_H_
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
}
|
|
||||||
#include <luabind/luabind.hpp>
|
|
||||||
|
|
||||||
#include "ExtractionHelperFunctions.h"
|
#include "ExtractionHelperFunctions.h"
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "LuaUtil.h"
|
|
||||||
|
|
||||||
#include "../DataStructures/ImportNode.h"
|
#include "../DataStructures/ImportNode.h"
|
||||||
|
#include "../Util/LuaUtil.h"
|
||||||
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class ScriptingEnvironment {
|
class ScriptingEnvironment {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "XMLParser.h"
|
||||||
|
|
||||||
|
#include "ExtractorStructs.h"
|
||||||
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/InputReaderFactory.h"
|
||||||
|
|
||||||
|
#include <boost/ref.hpp>
|
||||||
|
|
||||||
|
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
|
||||||
|
|
||||||
|
inputReader = inputReaderFactory(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool XMLParser::ReadHeader() {
|
||||||
|
return (xmlTextReaderRead( inputReader ) == 1);
|
||||||
|
}
|
||||||
|
bool XMLParser::Parse() {
|
||||||
|
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||||
|
const int type = xmlTextReaderNodeType( inputReader );
|
||||||
|
|
||||||
|
//1 is Element
|
||||||
|
if ( type != 1 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlChar* currentName = xmlTextReaderName( inputReader );
|
||||||
|
if ( currentName == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||||
|
ImportNode n = _ReadXMLNode();
|
||||||
|
ParseNodeInLua( n, luaState );
|
||||||
|
extractor_callbacks->nodeFunction(n);
|
||||||
|
// if(!extractor_callbacks->nodeFunction(n))
|
||||||
|
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||||
|
ExtractionWay way = _ReadXMLWay( );
|
||||||
|
ParseWayInLua( way, luaState );
|
||||||
|
extractor_callbacks->wayFunction(way);
|
||||||
|
// if(!extractor_callbacks->wayFunction(way))
|
||||||
|
// std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||||
|
}
|
||||||
|
if( use_turn_restrictions ) {
|
||||||
|
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||||
|
_RawRestrictionContainer r = _ReadXMLRestriction();
|
||||||
|
if(r.fromWay != UINT_MAX) {
|
||||||
|
if(!extractor_callbacks->restrictionFunction(r)) {
|
||||||
|
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree( currentName );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
|
||||||
|
_RawRestrictionContainer restriction;
|
||||||
|
std::string except_tag_string;
|
||||||
|
|
||||||
|
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||||
|
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||||
|
const int childType = xmlTextReaderNodeType( inputReader );
|
||||||
|
if ( childType != 1 && childType != 15 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||||
|
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||||
|
if ( childName == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
||||||
|
xmlFree( childName );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( childType != 1 ) {
|
||||||
|
xmlFree( childName );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||||
|
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||||
|
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||||
|
if ( k != NULL && value != NULL ) {
|
||||||
|
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
||||||
|
if(0 == std::string((const char *) value).find("only_")) {
|
||||||
|
restriction.restriction.flags.isOnly = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
|
||||||
|
except_tag_string = (const char*) value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( k != NULL ) {
|
||||||
|
xmlFree( k );
|
||||||
|
}
|
||||||
|
if ( value != NULL ) {
|
||||||
|
xmlFree( value );
|
||||||
|
}
|
||||||
|
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
||||||
|
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||||
|
if ( ref != NULL ) {
|
||||||
|
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
|
||||||
|
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
||||||
|
|
||||||
|
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||||
|
restriction.toWay = stringToUint((const char*) ref);
|
||||||
|
}
|
||||||
|
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
||||||
|
restriction.fromWay = stringToUint((const char*) ref);
|
||||||
|
}
|
||||||
|
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
||||||
|
restriction.restriction.viaNode = stringToUint((const char*) ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NULL != type) {
|
||||||
|
xmlFree( type );
|
||||||
|
}
|
||||||
|
if(NULL != role) {
|
||||||
|
xmlFree( role );
|
||||||
|
}
|
||||||
|
if(NULL != ref) {
|
||||||
|
xmlFree( ref );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree( childName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ShouldIgnoreRestriction(except_tag_string) ) {
|
||||||
|
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
|
||||||
|
}
|
||||||
|
return restriction;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExtractionWay XMLParser::_ReadXMLWay() {
|
||||||
|
ExtractionWay way;
|
||||||
|
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||||
|
const int depth = xmlTextReaderDepth( inputReader );
|
||||||
|
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||||
|
const int childType = xmlTextReaderNodeType( inputReader );
|
||||||
|
if ( childType != 1 && childType != 15 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||||
|
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||||
|
if ( childName == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||||
|
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||||
|
way.id = stringToUint((char*)id);
|
||||||
|
xmlFree(id);
|
||||||
|
xmlFree( childName );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( childType != 1 ) {
|
||||||
|
xmlFree( childName );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||||
|
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||||
|
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||||
|
// cout << "->k=" << k << ", v=" << value << endl;
|
||||||
|
if ( k != NULL && value != NULL ) {
|
||||||
|
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
|
||||||
|
}
|
||||||
|
if ( k != NULL ) {
|
||||||
|
xmlFree( k );
|
||||||
|
}
|
||||||
|
if ( value != NULL ) {
|
||||||
|
xmlFree( value );
|
||||||
|
}
|
||||||
|
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
||||||
|
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
||||||
|
if ( ref != NULL ) {
|
||||||
|
way.path.push_back( stringToUint(( const char* ) ref ) );
|
||||||
|
xmlFree( ref );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlFree( childName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return way;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImportNode XMLParser::_ReadXMLNode() {
|
||||||
|
ImportNode node;
|
||||||
|
|
||||||
|
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
||||||
|
if ( attribute != NULL ) {
|
||||||
|
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) );
|
||||||
|
xmlFree( attribute );
|
||||||
|
}
|
||||||
|
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
||||||
|
if ( attribute != NULL ) {
|
||||||
|
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ));
|
||||||
|
xmlFree( attribute );
|
||||||
|
}
|
||||||
|
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
||||||
|
if ( attribute != NULL ) {
|
||||||
|
node.id = stringToUint(( const char* ) attribute );
|
||||||
|
xmlFree( attribute );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
||||||
|
const int depth = xmlTextReaderDepth( inputReader );
|
||||||
|
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
||||||
|
const int childType = xmlTextReaderNodeType( inputReader );
|
||||||
|
// 1 = Element, 15 = EndElement
|
||||||
|
if ( childType != 1 && childType != 15 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int childDepth = xmlTextReaderDepth( inputReader );
|
||||||
|
xmlChar* childName = xmlTextReaderName( inputReader );
|
||||||
|
if ( childName == NULL ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||||
|
xmlFree( childName );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( childType != 1 ) {
|
||||||
|
xmlFree( childName );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
||||||
|
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
||||||
|
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
||||||
|
if ( k != NULL && value != NULL ) {
|
||||||
|
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
||||||
|
}
|
||||||
|
if ( k != NULL ) {
|
||||||
|
xmlFree( k );
|
||||||
|
}
|
||||||
|
if ( value != NULL ) {
|
||||||
|
xmlFree( value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFree( childName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
+27
-289
@@ -1,308 +1,46 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
open source routing machine
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XMLPARSER_H_
|
#ifndef XMLPARSER_H_
|
||||||
#define XMLPARSER_H_
|
#define XMLPARSER_H_
|
||||||
|
|
||||||
#include <boost/ref.hpp>
|
#include "BaseParser.h"
|
||||||
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
#include <libxml/xmlreader.h>
|
#include <libxml/xmlreader.h>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "BaseParser.h"
|
|
||||||
#include "ExtractorStructs.h"
|
|
||||||
#include "ExtractorCallbacks.h"
|
|
||||||
#include "ScriptingEnvironment.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/InputReaderFactory.h"
|
|
||||||
|
|
||||||
class XMLParser : public BaseParser<ExtractorCallbacks, _Node, _RawRestrictionContainer, _Way> {
|
class XMLParser : public BaseParser {
|
||||||
public:
|
public:
|
||||||
XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){
|
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||||
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
|
bool ReadHeader();
|
||||||
inputReader = inputReaderFactory(filename);
|
bool Parse();
|
||||||
}
|
|
||||||
virtual ~XMLParser() {}
|
|
||||||
|
|
||||||
void RegisterCallbacks(ExtractorCallbacks * em) {
|
|
||||||
externalMemory = em;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
|
|
||||||
myLuaState = _se.getLuaStateForThreadID(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Init() {
|
|
||||||
return (xmlTextReaderRead( inputReader ) == 1);
|
|
||||||
}
|
|
||||||
bool Parse() {
|
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
|
||||||
const int type = xmlTextReaderNodeType( inputReader );
|
|
||||||
|
|
||||||
//1 is Element
|
|
||||||
if ( type != 1 )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
xmlChar* currentName = xmlTextReaderName( inputReader );
|
|
||||||
if ( currentName == NULL )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
|
||||||
ImportNode n = _ReadXMLNode( );
|
|
||||||
/** Pass the unpacked node to the LUA call back **/
|
|
||||||
try {
|
|
||||||
luabind::call_function<int>(
|
|
||||||
myLuaState,
|
|
||||||
"node_function",
|
|
||||||
boost::ref(n)
|
|
||||||
);
|
|
||||||
if(!externalMemory->nodeFunction(n))
|
|
||||||
std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
cerr << er.what() << endl;
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
} catch (std::exception & e) {
|
|
||||||
ERR(e.what());
|
|
||||||
} catch (...) {
|
|
||||||
ERR("Unknown error occurred during XML node parsing!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
|
||||||
string name;
|
|
||||||
_Way way = _ReadXMLWay( );
|
|
||||||
|
|
||||||
/** Pass the unpacked way to the LUA call back **/
|
|
||||||
try {
|
|
||||||
luabind::call_function<int>(
|
|
||||||
myLuaState,
|
|
||||||
"way_function",
|
|
||||||
boost::ref(way),
|
|
||||||
way.path.size()
|
|
||||||
);
|
|
||||||
if(!externalMemory->wayFunction(way)) {
|
|
||||||
std::cerr << "[PBFParser] way not parsed" << std::endl;
|
|
||||||
}
|
|
||||||
} catch (const luabind::error &er) {
|
|
||||||
cerr << er.what() << endl;
|
|
||||||
lua_State* Ler=er.state();
|
|
||||||
report_errors(Ler, -1);
|
|
||||||
} catch (std::exception & e) {
|
|
||||||
ERR(e.what());
|
|
||||||
} catch (...) {
|
|
||||||
ERR("Unknown error occurred during XML way parsing!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
|
|
||||||
_RawRestrictionContainer r = _ReadXMLRestriction();
|
|
||||||
if(r.fromWay != UINT_MAX) {
|
|
||||||
if(!externalMemory->restrictionFunction(r)) {
|
|
||||||
std::cerr << "[XMLParser] restriction not parsed" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree( currentName );
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_RawRestrictionContainer _ReadXMLRestriction ( ) {
|
_RawRestrictionContainer _ReadXMLRestriction();
|
||||||
_RawRestrictionContainer restriction;
|
ExtractionWay _ReadXMLWay();
|
||||||
|
ImportNode _ReadXMLNode();
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
|
||||||
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
|
||||||
if ( childType != 1 && childType != 15 )
|
|
||||||
continue;
|
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
|
||||||
if ( childName == NULL )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
|
|
||||||
xmlFree( childName );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( childType != 1 ) {
|
|
||||||
xmlFree( childName );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
|
||||||
if ( k != NULL && value != NULL ) {
|
|
||||||
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
|
|
||||||
if(0 == std::string((const char *) value).find("only_"))
|
|
||||||
restriction.restriction.flags.isOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if ( k != NULL )
|
|
||||||
xmlFree( k );
|
|
||||||
if ( value != NULL )
|
|
||||||
xmlFree( value );
|
|
||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) {
|
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
|
||||||
if ( ref != NULL ) {
|
|
||||||
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
|
|
||||||
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
|
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
|
||||||
restriction.toWay = atoi((const char*) ref);
|
|
||||||
}
|
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
|
|
||||||
restriction.fromWay = atoi((const char*) ref);
|
|
||||||
}
|
|
||||||
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
|
|
||||||
restriction.restriction.viaNode = atoi((const char*) ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(NULL != type)
|
|
||||||
xmlFree( type );
|
|
||||||
if(NULL != role)
|
|
||||||
xmlFree( role );
|
|
||||||
if(NULL != ref)
|
|
||||||
xmlFree( ref );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree( childName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return restriction;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Way _ReadXMLWay( ) {
|
|
||||||
_Way way;
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
|
||||||
const int depth = xmlTextReaderDepth( inputReader );
|
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
|
||||||
if ( childType != 1 && childType != 15 )
|
|
||||||
continue;
|
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
|
||||||
if ( childName == NULL )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
|
|
||||||
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
|
||||||
way.id = atoi((char*)id);
|
|
||||||
xmlFree(id);
|
|
||||||
xmlFree( childName );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( childType != 1 ) {
|
|
||||||
xmlFree( childName );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
|
||||||
// cout << "->k=" << k << ", v=" << value << endl;
|
|
||||||
if ( k != NULL && value != NULL ) {
|
|
||||||
|
|
||||||
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value));
|
|
||||||
}
|
|
||||||
if ( k != NULL )
|
|
||||||
xmlFree( k );
|
|
||||||
if ( value != NULL )
|
|
||||||
xmlFree( value );
|
|
||||||
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
|
|
||||||
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
|
|
||||||
if ( ref != NULL ) {
|
|
||||||
way.path.push_back( atoi(( const char* ) ref ) );
|
|
||||||
xmlFree( ref );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree( childName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return way;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImportNode _ReadXMLNode( ) {
|
|
||||||
ImportNode node;
|
|
||||||
|
|
||||||
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" );
|
|
||||||
if ( attribute != NULL ) {
|
|
||||||
node.lat = static_cast<NodeID>(100000.*atof(( const char* ) attribute ) );
|
|
||||||
xmlFree( attribute );
|
|
||||||
}
|
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" );
|
|
||||||
if ( attribute != NULL ) {
|
|
||||||
node.lon = static_cast<NodeID>(100000.*atof(( const char* ) attribute ));
|
|
||||||
xmlFree( attribute );
|
|
||||||
}
|
|
||||||
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
|
|
||||||
if ( attribute != NULL ) {
|
|
||||||
node.id = atoi(( const char* ) attribute );
|
|
||||||
xmlFree( attribute );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
|
|
||||||
const int depth = xmlTextReaderDepth( inputReader );
|
|
||||||
while ( xmlTextReaderRead( inputReader ) == 1 ) {
|
|
||||||
const int childType = xmlTextReaderNodeType( inputReader );
|
|
||||||
// 1 = Element, 15 = EndElement
|
|
||||||
if ( childType != 1 && childType != 15 )
|
|
||||||
continue;
|
|
||||||
const int childDepth = xmlTextReaderDepth( inputReader );
|
|
||||||
xmlChar* childName = xmlTextReaderName( inputReader );
|
|
||||||
if ( childName == NULL )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
|
|
||||||
xmlFree( childName );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( childType != 1 ) {
|
|
||||||
xmlFree( childName );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) {
|
|
||||||
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
|
|
||||||
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
|
|
||||||
if ( k != NULL && value != NULL ) {
|
|
||||||
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value)));
|
|
||||||
}
|
|
||||||
if ( k != NULL )
|
|
||||||
xmlFree( k );
|
|
||||||
if ( value != NULL )
|
|
||||||
xmlFree( value );
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlFree( childName );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
/* Input Reader */
|
|
||||||
xmlTextReaderPtr inputReader;
|
xmlTextReaderPtr inputReader;
|
||||||
|
|
||||||
//holds the callback functions and storage for our temporary data
|
|
||||||
ExtractorCallbacks * externalMemory;
|
|
||||||
|
|
||||||
lua_State *myLuaState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* XMLPARSER_H_ */
|
#endif /* XMLPARSER_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "OSRM.h"
|
||||||
|
|
||||||
|
OSRM::OSRM(const char * server_ini_path) {
|
||||||
|
if( !testDataFile(server_ini_path) ){
|
||||||
|
std::string error_message = std::string(server_ini_path) + " not found";
|
||||||
|
throw OSRMException(error_message.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
IniFile serverConfig(server_ini_path);
|
||||||
|
|
||||||
|
boost::filesystem::path base_path =
|
||||||
|
boost::filesystem::absolute(server_ini_path).parent_path();
|
||||||
|
|
||||||
|
if ( !serverConfig.Holds("hsgrData")) {
|
||||||
|
throw OSRMException("no ram index file name in server ini");
|
||||||
|
}
|
||||||
|
if ( !serverConfig.Holds("ramIndex") ) {
|
||||||
|
throw OSRMException("no mem index file name in server ini");
|
||||||
|
}
|
||||||
|
if ( !serverConfig.Holds("fileIndex") ) {
|
||||||
|
throw OSRMException("no nodes file name in server ini");
|
||||||
|
}
|
||||||
|
if ( !serverConfig.Holds("nodesData") ) {
|
||||||
|
throw OSRMException("no nodes file name in server ini");
|
||||||
|
}
|
||||||
|
if ( !serverConfig.Holds("edgesData") ) {
|
||||||
|
throw OSRMException("no edges file name in server ini");
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::path hsgr_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("hsgrData"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::filesystem::path ram_index_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("ramIndex"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::filesystem::path file_index_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("fileIndex"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
|
||||||
|
boost::filesystem::path node_data_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("nodesData"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
boost::filesystem::path edge_data_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("edgesData"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
boost::filesystem::path name_data_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("namesData"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
boost::filesystem::path timestamp_path = boost::filesystem::absolute(
|
||||||
|
serverConfig.GetParameter("timestamp"),
|
||||||
|
base_path
|
||||||
|
);
|
||||||
|
|
||||||
|
objects = new QueryObjectsStorage(
|
||||||
|
hsgr_path.string(),
|
||||||
|
ram_index_path.string(),
|
||||||
|
file_index_path.string(),
|
||||||
|
node_data_path.string(),
|
||||||
|
edge_data_path.string(),
|
||||||
|
name_data_path.string(),
|
||||||
|
timestamp_path.string()
|
||||||
|
);
|
||||||
|
|
||||||
|
RegisterPlugin(new HelloWorldPlugin());
|
||||||
|
RegisterPlugin(new LocatePlugin(objects));
|
||||||
|
RegisterPlugin(new NearestPlugin(objects));
|
||||||
|
RegisterPlugin(new TimestampPlugin(objects));
|
||||||
|
RegisterPlugin(new ViaRoutePlugin(objects));
|
||||||
|
}
|
||||||
|
|
||||||
|
OSRM::~OSRM() {
|
||||||
|
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, pluginMap) {
|
||||||
|
delete plugin_pointer.second;
|
||||||
|
}
|
||||||
|
delete objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
||||||
|
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||||
|
if( pluginMap.find(plugin->GetDescriptor()) != pluginMap.end() ) {
|
||||||
|
delete pluginMap[plugin->GetDescriptor()];
|
||||||
|
}
|
||||||
|
pluginMap.insert(std::make_pair(plugin->GetDescriptor(), plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||||
|
const PluginMap::const_iterator & iter = pluginMap.find(route_parameters.service);
|
||||||
|
if(pluginMap.end() != iter) {
|
||||||
|
reply.status = http::Reply::ok;
|
||||||
|
iter->second->HandleRequest(route_parameters, reply );
|
||||||
|
} else {
|
||||||
|
reply = http::Reply::stockReply(http::Reply::badRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSRM_H
|
||||||
|
#define OSRM_H
|
||||||
|
|
||||||
|
#include "OSRM.h"
|
||||||
|
|
||||||
|
#include "../Plugins/BasePlugin.h"
|
||||||
|
#include "../Plugins/HelloWorldPlugin.h"
|
||||||
|
#include "../Plugins/LocatePlugin.h"
|
||||||
|
#include "../Plugins/NearestPlugin.h"
|
||||||
|
#include "../Plugins/TimestampPlugin.h"
|
||||||
|
#include "../Plugins/ViaRoutePlugin.h"
|
||||||
|
#include "../Server/DataStructures/RouteParameters.h"
|
||||||
|
#include "../Util/IniFile.h"
|
||||||
|
#include "../Util/InputFileUtil.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Server/BasicDatastructures.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class OSRM : boost::noncopyable {
|
||||||
|
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||||
|
QueryObjectsStorage * objects;
|
||||||
|
public:
|
||||||
|
OSRM(const char * server_ini_path);
|
||||||
|
~OSRM();
|
||||||
|
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||||
|
private:
|
||||||
|
void RegisterPlugin(BasePlugin * plugin);
|
||||||
|
PluginMap pluginMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //OSRM_H
|
||||||
+17
-6
@@ -21,21 +21,32 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef BASEPLUGIN_H_
|
#ifndef BASEPLUGIN_H_
|
||||||
#define BASEPLUGIN_H_
|
#define BASEPLUGIN_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include "../DataStructures/Coordinate.h"
|
||||||
|
#include "../Server/BasicDatastructures.h"
|
||||||
|
#include "../Server/DataStructures/RouteParameters.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "RouteParameters.h"
|
|
||||||
#include "../Server/BasicDatastructures.h"
|
|
||||||
|
|
||||||
class BasePlugin {
|
class BasePlugin {
|
||||||
public:
|
public:
|
||||||
BasePlugin() { }
|
BasePlugin() { }
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BasePlugin() { }
|
virtual ~BasePlugin() { }
|
||||||
virtual std::string GetDescriptor() const = 0;
|
virtual const std::string & GetDescriptor() const = 0;
|
||||||
virtual std::string GetVersionString() const = 0 ;
|
|
||||||
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
|
virtual void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) = 0;
|
||||||
|
|
||||||
|
inline bool checkCoord(const FixedPointCoordinate & c) {
|
||||||
|
if(
|
||||||
|
c.lat > 90*COORDINATE_PRECISION ||
|
||||||
|
c.lat < -90*COORDINATE_PRECISION ||
|
||||||
|
c.lon > 180*COORDINATE_PRECISION ||
|
||||||
|
c.lon < -180*COORDINATE_PRECISION
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BASEPLUGIN_H_ */
|
#endif /* BASEPLUGIN_H_ */
|
||||||
|
|||||||
+25
-12
@@ -1,24 +1,35 @@
|
|||||||
/*
|
/*
|
||||||
* LocatePlugin.h
|
open source routing machine
|
||||||
*
|
Copyright (C) Dennis Luxen, 2010
|
||||||
* Created on: 01.01.2011
|
|
||||||
* Author: dennis
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef HELLOWORLDPLUGIN_H_
|
#ifndef HELLOWORLDPLUGIN_H_
|
||||||
#define HELLOWORLDPLUGIN_H_
|
#define HELLOWORLDPLUGIN_H_
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
class HelloWorldPlugin : public BasePlugin {
|
class HelloWorldPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
HelloWorldPlugin() {}
|
HelloWorldPlugin() : descriptor_string("hello"){}
|
||||||
virtual ~HelloWorldPlugin() { /*std::cout << GetDescriptor() << " destructor" << std::endl;*/ }
|
virtual ~HelloWorldPlugin() { }
|
||||||
std::string GetDescriptor() const { return std::string("hello"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.1a"); }
|
|
||||||
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
@@ -35,7 +46,7 @@ public:
|
|||||||
content << "language: " << routeParameters.language << "<br>";
|
content << "language: " << routeParameters.language << "<br>";
|
||||||
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
|
content << "Number of locations: " << routeParameters.coordinates.size() << "\n";
|
||||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||||
content << " [" << i << "] " << routeParameters.coordinates[i].lat/100000. << "," << routeParameters.coordinates[i].lon/100000. << "\n";
|
content << " [" << i << "] " << routeParameters.coordinates[i].lat/COORDINATE_PRECISION << "," << routeParameters.coordinates[i].lon/COORDINATE_PRECISION << "\n";
|
||||||
}
|
}
|
||||||
content << "Number of hints: " << routeParameters.hints.size() << "\n";
|
content << "Number of hints: " << routeParameters.hints.size() << "\n";
|
||||||
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
for(unsigned i = 0; i < routeParameters.hints.size(); ++i) {
|
||||||
@@ -45,6 +56,8 @@ public:
|
|||||||
reply.content.append(content.str());
|
reply.content.append(content.str());
|
||||||
reply.content.append("</body></html>");
|
reply.content.append("</body></html>");
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* HELLOWORLDPLUGIN_H_ */
|
#endif /* HELLOWORLDPLUGIN_H_ */
|
||||||
|
|||||||
+10
-19
@@ -21,24 +21,20 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef LOCATEPLUGIN_H_
|
#ifndef LOCATEPLUGIN_H_
|
||||||
#define LOCATEPLUGIN_H_
|
#define LOCATEPLUGIN_H_
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
#include "../DataStructures/NodeInformationHelpDesk.h"
|
||||||
|
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This Plugin 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.
|
||||||
*/
|
*/
|
||||||
class LocatePlugin : public BasePlugin {
|
class LocatePlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
LocatePlugin(QueryObjectsStorage * objects) {
|
LocatePlugin(QueryObjectsStorage * objects) : descriptor_string("locate") {
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
nodeHelpDesk = objects->nodeHelpDesk;
|
||||||
}
|
}
|
||||||
std::string GetDescriptor() const { return std::string("locate"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
@@ -51,13 +47,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//query to helpdesk
|
//query to helpdesk
|
||||||
_Coordinate result;
|
FixedPointCoordinate result;
|
||||||
std::string JSONParameter, tmp;
|
std::string tmp;
|
||||||
//json
|
//json
|
||||||
|
|
||||||
// JSONParameter = routeParameters.options.Find("jsonp");
|
// JSONParameter = routeParameters.options.Find("jsonp");
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += JSONParameter;
|
reply.content += routeParameters.jsonpParameter;
|
||||||
reply.content += "(";
|
reply.content += "(";
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
@@ -82,7 +78,7 @@ public:
|
|||||||
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
|
reply.content += ",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"";
|
||||||
reply.content += ("}");
|
reply.content += ("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != JSONParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")";
|
reply.content += ")";
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
@@ -99,15 +95,10 @@ public:
|
|||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
inline bool checkCoord(const _Coordinate & c) {
|
|
||||||
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
NodeInformationHelpDesk * nodeHelpDesk;
|
||||||
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LOCATEPLUGIN_H_ */
|
#endif /* LOCATEPLUGIN_H_ */
|
||||||
|
|||||||
+12
-19
@@ -21,14 +21,10 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef NearestPlugin_H_
|
#ifndef NearestPlugin_H_
|
||||||
#define NearestPlugin_H_
|
#define NearestPlugin_H_
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
|
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
#include "../DataStructures/NodeInformationHelpDesk.h"
|
||||||
|
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -36,14 +32,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
*/
|
*/
|
||||||
class NearestPlugin : public BasePlugin {
|
class NearestPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
NearestPlugin(QueryObjectsStorage * objects) : names(objects->names) {
|
NearestPlugin(QueryObjectsStorage * objects )
|
||||||
|
:
|
||||||
|
names(objects->names),
|
||||||
|
descriptor_string("nearest")
|
||||||
|
{
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
nodeHelpDesk = objects->nodeHelpDesk;
|
||||||
|
|
||||||
descriptorTable.Set("", 0); //default descriptor
|
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
||||||
descriptorTable.Set("json", 1);
|
descriptorTable.insert(std::make_pair("json", 1));
|
||||||
}
|
}
|
||||||
std::string GetDescriptor() const { return std::string("nearest"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if(!routeParameters.coordinates.size()) {
|
if(!routeParameters.coordinates.size()) {
|
||||||
@@ -60,7 +59,6 @@ public:
|
|||||||
nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
|
nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel);
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
std::string JSONParameter;
|
|
||||||
//json
|
//json
|
||||||
|
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
@@ -93,7 +91,7 @@ public:
|
|||||||
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
|
reply.content += ",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"";
|
||||||
reply.content += ("}");
|
reply.content += ("}");
|
||||||
reply.headers.resize(3);
|
reply.headers.resize(3);
|
||||||
if("" != JSONParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")";
|
reply.content += ")";
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
@@ -109,17 +107,12 @@ public:
|
|||||||
intToString(reply.content.size(), tmp);
|
intToString(reply.content.size(), tmp);
|
||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
inline bool checkCoord(const _Coordinate & c) {
|
|
||||||
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
private:
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
NodeInformationHelpDesk * nodeHelpDesk;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
HashTable<std::string, unsigned> descriptorTable;
|
||||||
std::vector<std::string> & names;
|
std::vector<std::string> & names;
|
||||||
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NearestPlugin_H_ */
|
#endif /* NearestPlugin_H_ */
|
||||||
|
|||||||
@@ -21,17 +21,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef TIMESTAMPPLUGIN_H_
|
#ifndef TIMESTAMPPLUGIN_H_
|
||||||
#define TIMESTAMPPLUGIN_H_
|
#define TIMESTAMPPLUGIN_H_
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
|
|
||||||
class TimestampPlugin : public BasePlugin {
|
class TimestampPlugin : public BasePlugin {
|
||||||
public:
|
public:
|
||||||
TimestampPlugin(QueryObjectsStorage * o) : objects(o) {
|
TimestampPlugin(QueryObjectsStorage * o)
|
||||||
}
|
: objects(o), descriptor_string("timestamp")
|
||||||
std::string GetDescriptor() const { return std::string("timestamp"); }
|
{ }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
|
||||||
@@ -70,6 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
QueryObjectsStorage * objects;
|
QueryObjectsStorage * objects;
|
||||||
|
std::string descriptor_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* TIMESTAMPPLUGIN_H_ */
|
#endif /* TIMESTAMPPLUGIN_H_ */
|
||||||
|
|||||||
+40
-48
@@ -21,29 +21,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef VIAROUTEPLUGIN_H_
|
#ifndef VIAROUTEPLUGIN_H_
|
||||||
#define VIAROUTEPLUGIN_H_
|
#define VIAROUTEPLUGIN_H_
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
|
||||||
|
|
||||||
#include "../Algorithms/ObjectToBase64.h"
|
#include "../Algorithms/ObjectToBase64.h"
|
||||||
|
|
||||||
#include "../Descriptors/BaseDescriptor.h"
|
|
||||||
#include "../Descriptors/GPXDescriptor.h"
|
|
||||||
#include "../Descriptors/JSONDescriptor.h"
|
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/StaticGraph.h"
|
#include "../DataStructures/StaticGraph.h"
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
|
#include "../Descriptors/GPXDescriptor.h"
|
||||||
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
|
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class ViaRoutePlugin : public BasePlugin {
|
class ViaRoutePlugin : public BasePlugin {
|
||||||
private:
|
private:
|
||||||
@@ -51,27 +46,30 @@ private:
|
|||||||
std::vector<std::string> & names;
|
std::vector<std::string> & names;
|
||||||
StaticGraph<QueryEdge::EdgeData> * graph;
|
StaticGraph<QueryEdge::EdgeData> * graph;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
HashTable<std::string, unsigned> descriptorTable;
|
||||||
std::string pluginDescriptorString;
|
SearchEngine * searchEnginePtr;
|
||||||
SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > * searchEngine;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
|
ViaRoutePlugin(QueryObjectsStorage * objects)
|
||||||
|
:
|
||||||
|
names(objects->names),
|
||||||
|
descriptor_string("viaroute")
|
||||||
|
{
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
nodeHelpDesk = objects->nodeHelpDesk;
|
||||||
graph = objects->graph;
|
graph = objects->graph;
|
||||||
|
|
||||||
searchEngine = new SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> >(graph, nodeHelpDesk, names);
|
searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names);
|
||||||
|
|
||||||
descriptorTable.Set("", 0); //default descriptor
|
descriptorTable.insert(std::make_pair("" , 0));
|
||||||
descriptorTable.Set("json", 0);
|
descriptorTable.insert(std::make_pair("json", 0));
|
||||||
descriptorTable.Set("gpx", 1);
|
descriptorTable.insert(std::make_pair("gpx" , 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() {
|
||||||
delete searchEngine;
|
delete searchEnginePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDescriptor() const { return pluginDescriptorString; }
|
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||||
std::string GetVersionString() const { return std::string("0.3 (DL)"); }
|
|
||||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||||
//check number of parameters
|
//check number of parameters
|
||||||
if( 2 > routeParameters.coordinates.size() ) {
|
if( 2 > routeParameters.coordinates.size() ) {
|
||||||
@@ -93,15 +91,15 @@ public:
|
|||||||
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size());
|
||||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) {
|
||||||
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) {
|
||||||
// INFO("Decoding hint: " << routeParameters.hints[i] << " for location index " << i);
|
// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i;
|
||||||
DecodeObjectFromBase64(phantomNodeVector[i], routeParameters.hints[i]);
|
DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]);
|
||||||
if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
|
if(phantomNodeVector[i].isValid(nodeHelpDesk->getNumberOfNodes())) {
|
||||||
// INFO("Decoded hint " << i << " successfully");
|
// SimpleLogger().Write() << "Decoded hint " << i << " successfully";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INFO("Brute force lookup of coordinate " << i);
|
// SimpleLogger().Write() << "Brute force lookup of coordinate " << i;
|
||||||
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
|
searchEnginePtr->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) {
|
||||||
@@ -111,21 +109,21 @@ public:
|
|||||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||||
}
|
}
|
||||||
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
||||||
// INFO("Checking for alternative paths");
|
// SimpleLogger().Write() << "Checking for alternative paths";
|
||||||
searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
if(INT_MAX == rawRoute.lengthOfShortestPath ) {
|
||||||
DEBUG( "Error occurred, single path not found" );
|
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||||
}
|
}
|
||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
|
|
||||||
//TODO: Move to member as smart pointer
|
//TODO: Move to member as smart pointer
|
||||||
BaseDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > > * desc;
|
BaseDescriptor * desc;
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content += routeParameters.jsonpParameter;
|
||||||
reply.content += "(";
|
reply.content += "(";
|
||||||
@@ -140,28 +138,28 @@ public:
|
|||||||
|
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
case 0:
|
||||||
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
|
desc = new JSONDescriptor();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
desc = new GPXDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
|
desc = new GPXDescriptor();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
|
desc = new JSONDescriptor();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomNodes phantomNodes;
|
PhantomNodes phantomNodes;
|
||||||
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom;
|
||||||
// INFO("Start location: " << phantomNodes.startPhantom.location)
|
// 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;
|
||||||
// INFO("TargetLocation: " << phantomNodes.targetPhantom.location);
|
// SimpleLogger().Write() << "TargetLocation: " << phantomNodes.targetPhantom.location;
|
||||||
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
|
// SimpleLogger().Write() << "Number of segments: " << rawRoute.segmentEndCoordinates.size();
|
||||||
desc->SetConfig(descriptorConfig);
|
desc->SetConfig(descriptorConfig);
|
||||||
|
|
||||||
desc->Run(reply, rawRoute, phantomNodes, *searchEngine);
|
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")\n";
|
reply.content += ")\n";
|
||||||
}
|
}
|
||||||
@@ -204,7 +202,6 @@ public:
|
|||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,12 +209,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
inline bool checkCoord(const _Coordinate & c) {
|
std::string descriptor_string;
|
||||||
if(c.lat > 90*100000 || c.lat < -90*100000 || c.lon > 180*100000 || c.lon <-180*100000) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# Readme
|
||||||
|
|
||||||
|
For instructions on how to compile and run OSRM, please consult the Wiki at
|
||||||
|
|
||||||
|
https://github.com/DennisOSRM/Project-OSRM/wiki
|
||||||
|
|
||||||
|
or use our free and daily updated online service at
|
||||||
|
|
||||||
|
http://map.project-osrm.org
|
||||||
|
|
||||||
|
## References in publications
|
||||||
|
|
||||||
|
When using the code in a (scientific) publication, please cite
|
||||||
|
|
||||||
|
```
|
||||||
|
@inproceedings{luxen-vetter-2011,
|
||||||
|
author = {Luxen, Dennis and Vetter, Christian},
|
||||||
|
title = {Real-time routing with OpenStreetMap data},
|
||||||
|
booktitle = {Proceedings of the 19th ACM SIGSPATIAL International Conference on Advances in Geographic Information Systems},
|
||||||
|
series = {GIS '11},
|
||||||
|
year = {2011},
|
||||||
|
isbn = {978-1-4503-1031-4},
|
||||||
|
location = {Chicago, Illinois},
|
||||||
|
pages = {513--516},
|
||||||
|
numpages = {4},
|
||||||
|
url = {http://doi.acm.org/10.1145/2093973.2094062},
|
||||||
|
doi = {10.1145/2093973.2094062},
|
||||||
|
acmid = {2094062},
|
||||||
|
publisher = {ACM},
|
||||||
|
address = {New York, NY, USA},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current build status
|
||||||
|
|
||||||
|
| build config | branch | status |
|
||||||
|
|:-------------|:--------|:------------|
|
||||||
|
| Project OSRM | master | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
||||||
|
| Project OSRM | develop | [](https://travis-ci.org/DennisOSRM/Project-OSRM) |
|
||||||
|
| LUAbind fork | master | [](https://travis-ci.org/DennisOSRM/luabind) |
|
||||||
@@ -4,9 +4,11 @@ require 'digest/sha1'
|
|||||||
require 'cucumber/rake/task'
|
require 'cucumber/rake/task'
|
||||||
require 'sys/proctable'
|
require 'sys/proctable'
|
||||||
|
|
||||||
|
BUILD_FOLDER = 'build'
|
||||||
DATA_FOLDER = 'sandbox'
|
DATA_FOLDER = 'sandbox'
|
||||||
PROFILE = 'bicycle'
|
PROFILE = 'bicycle'
|
||||||
OSRM_PORT = 5000
|
OSRM_PORT = 5000
|
||||||
|
PROFILES_FOLDER = '../profiles'
|
||||||
|
|
||||||
Cucumber::Rake::Task.new do |t|
|
Cucumber::Rake::Task.new do |t|
|
||||||
t.cucumber_opts = %w{--format pretty}
|
t.cucumber_opts = %w{--format pretty}
|
||||||
@@ -16,7 +18,7 @@ areas = {
|
|||||||
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
|
:kbh => { :country => 'denmark', :bbox => 'top=55.6972 left=12.5222 right=12.624 bottom=55.6376' },
|
||||||
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
|
:frd => { :country => 'denmark', :bbox => 'top=55.7007 left=12.4765 bottom=55.6576 right=12.5698' },
|
||||||
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
|
:regh => { :country => 'denmark', :bbox => 'top=56.164 left=11.792 bottom=55.403 right=12.731' },
|
||||||
:dk => { :country => 'denmark', :bbox => nil },
|
:denmark => { :country => 'denmark', :bbox => nil },
|
||||||
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
|
:skaane => { :country => 'sweden', :bbox => 'top=56.55 left=12.4 bottom=55.3 right=14.6' }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,11 +78,17 @@ end
|
|||||||
|
|
||||||
|
|
||||||
desc "Rebuild and run tests."
|
desc "Rebuild and run tests."
|
||||||
task :default => [:build, :cucumber]
|
task :default => [:build]
|
||||||
|
|
||||||
desc "Build using SConsstruct."
|
desc "Build using CMake."
|
||||||
task :build do
|
task :build do
|
||||||
system "scons"
|
if Dir.exists? BUILD_FOLDER
|
||||||
|
Dir.chdir BUILD_FOLDER do
|
||||||
|
system "make"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
system "mkdir build; cd build; cmake ..; make"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Setup config files."
|
desc "Setup config files."
|
||||||
@@ -98,8 +106,8 @@ desc "Download OSM data."
|
|||||||
task :download => :setup do
|
task :download => :setup do
|
||||||
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
||||||
puts "Downloading..."
|
puts "Downloading..."
|
||||||
puts "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||||
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||||
if osm_data_area_bbox
|
if osm_data_area_bbox
|
||||||
puts "Cropping and converting to protobuffer..."
|
puts "Cropping and converting to protobuffer..."
|
||||||
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
||||||
@@ -116,13 +124,27 @@ end
|
|||||||
desc "Reprocess OSM data."
|
desc "Reprocess OSM data."
|
||||||
task :process => :setup do
|
task :process => :setup do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
|
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
||||||
puts
|
puts
|
||||||
raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
|
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc "Extract OSM data."
|
||||||
|
task :extract => :setup do
|
||||||
|
Dir.chdir DATA_FOLDER do
|
||||||
|
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Prepare OSM data."
|
||||||
|
task :prepare => :setup do
|
||||||
|
Dir.chdir DATA_FOLDER do
|
||||||
|
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
desc "Delete preprocessing files."
|
desc "Delete preprocessing files."
|
||||||
task :clean do
|
task :clean do
|
||||||
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
|
File.delete *Dir.glob("#{DATA_FOLDER}/*.osrm")
|
||||||
@@ -139,7 +161,7 @@ desc "Run the routing server in the terminal. Press Ctrl-C to stop."
|
|||||||
task :run => :setup do
|
task :run => :setup do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
write_server_ini osm_data_area_name
|
write_server_ini osm_data_area_name
|
||||||
system "../osrm-routed"
|
system "../#{BUILD_FOLDER}/osrm-routed"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -148,7 +170,7 @@ task :up => :setup do
|
|||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
abort("Already up.") if up?
|
abort("Already up.") if up?
|
||||||
write_server_ini osm_data_area_name
|
write_server_ini osm_data_area_name
|
||||||
pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log')
|
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log")
|
||||||
timeout = 5
|
timeout = 5
|
||||||
(timeout*10).times do
|
(timeout*10).times do
|
||||||
begin
|
begin
|
||||||
|
|||||||
@@ -21,23 +21,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef ALTERNATIVEROUTES_H_
|
#ifndef ALTERNATIVEROUTES_H_
|
||||||
#define ALTERNATIVEROUTES_H_
|
#define ALTERNATIVEROUTES_H_
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include "BasicRoutingInterface.h"
|
#include "BasicRoutingInterface.h"
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
const double VIAPATH_ALPHA = 0.25;
|
const double VIAPATH_ALPHA = 0.15;
|
||||||
const double VIAPATH_EPSILON = 0.25;
|
const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer
|
||||||
const double VIAPATH_GAMMA = 0.80;
|
const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest.
|
||||||
|
|
||||||
template<class QueryDataT>
|
template<class QueryDataT>
|
||||||
class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{
|
class AlternativeRouting : private BasicRoutingInterface<QueryDataT> {
|
||||||
typedef BasicRoutingInterface<QueryDataT> super;
|
typedef BasicRoutingInterface<QueryDataT> super;
|
||||||
typedef std::pair<NodeID, int> PreselectedNode;
|
typedef typename QueryDataT::Graph SearchGraph;
|
||||||
typedef typename QueryDataT::HeapPtr HeapPtr;
|
typedef typename QueryDataT::QueryHeap QueryHeap;
|
||||||
typedef std::pair<NodeID, NodeID> UnpackEdge;
|
typedef std::pair<NodeID, NodeID> SearchSpaceEdge;
|
||||||
|
|
||||||
struct RankedCandidateNode {
|
struct RankedCandidateNode {
|
||||||
RankedCandidateNode(NodeID n, int l, 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;
|
||||||
@@ -45,9 +46,12 @@ class AlternativeRouting : private BasicRoutingInterface<QueryDataT>{
|
|||||||
return (2*length + sharing) < (2*other.length + other.sharing);
|
return (2*length + sharing) < (2*other.length + other.sharing);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SearchGraph * search_graph;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AlternativeRouting(QueryDataT & qd) : super(qd) { }
|
AlternativeRouting(QueryDataT & qd) : super(qd), search_graph(qd.graph) { }
|
||||||
|
|
||||||
~AlternativeRouting() {}
|
~AlternativeRouting() {}
|
||||||
|
|
||||||
@@ -59,81 +63,115 @@ public:
|
|||||||
|
|
||||||
std::vector<NodeID> alternativePath;
|
std::vector<NodeID> alternativePath;
|
||||||
std::vector<NodeID> viaNodeCandidates;
|
std::vector<NodeID> viaNodeCandidates;
|
||||||
std::vector <NodeID> packedShortestPath;
|
std::vector<SearchSpaceEdge> forward_search_space;
|
||||||
std::vector<PreselectedNode> nodesThatPassPreselection;
|
std::vector<SearchSpaceEdge> reverse_search_space;
|
||||||
|
|
||||||
HeapPtr & forwardHeap = super::_queryData.forwardHeap;
|
//Initialize Queues, semi-expensive because access to TSS invokes a system call
|
||||||
HeapPtr & backwardHeap = super::_queryData.backwardHeap;
|
|
||||||
HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
|
|
||||||
HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
|
|
||||||
|
|
||||||
//Initialize Queues
|
|
||||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
||||||
int _upperBound = INT_MAX;
|
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||||
NodeID middle = UINT_MAX;
|
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
||||||
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
|
||||||
|
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
||||||
|
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
||||||
|
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
||||||
|
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
||||||
|
|
||||||
|
int upper_bound_to_shortest_path_distance = INT_MAX;
|
||||||
|
NodeID middle_node = UINT_MAX;
|
||||||
|
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||||
if(phantomNodePair.startPhantom.isBidirected() ) {
|
if(phantomNodePair.startPhantom.isBidirected() ) {
|
||||||
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||||
}
|
}
|
||||||
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
||||||
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1)
|
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
||||||
+ (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1);
|
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
||||||
|
|
||||||
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
//exploration dijkstra from nodes s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
||||||
while(forwardHeap->Size() + backwardHeap->Size() > 0){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size())){
|
||||||
if(forwardHeap->Size() > 0){
|
if(0 < forward_heap1.Size()){
|
||||||
AlternativeRoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, 2*offset, true, viaNodeCandidates);
|
AlternativeRoutingStep<true >(forward_heap1, reverse_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, forward_search_space, forward_offset);
|
||||||
}
|
}
|
||||||
if(backwardHeap->Size() > 0){
|
if(0 < reverse_heap1.Size()){
|
||||||
AlternativeRoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, 2*offset, false, viaNodeCandidates);
|
AlternativeRoutingStep<false>(reverse_heap1, forward_heap1, &middle_node, &upper_bound_to_shortest_path_distance, viaNodeCandidates, reverse_search_space, reverse_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::sort(viaNodeCandidates.begin(), viaNodeCandidates.end());
|
sort_unique_resize(viaNodeCandidates);
|
||||||
int size = std::unique(viaNodeCandidates.begin(), viaNodeCandidates.end())- viaNodeCandidates.begin();
|
|
||||||
viaNodeCandidates.resize(size);
|
|
||||||
|
|
||||||
//save (packed) shortest path of shortest path and keep it for later use.
|
std::vector<NodeID> packed_forward_path;
|
||||||
//we need it during the checks and dont want to recompute it always
|
std::vector<NodeID> packed_reverse_path;
|
||||||
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle, packedShortestPath);
|
|
||||||
|
|
||||||
//ch-pruning of via nodes in both search spaces
|
super::RetrievePackedPathFromSingleHeap(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_reverse_sharing;
|
||||||
|
|
||||||
|
unsigned index_into_forward_path = 0;
|
||||||
|
//sweep over search space, compute forward sharing for each current edge (u,v)
|
||||||
|
BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) {
|
||||||
|
const NodeID u = current_edge.first;
|
||||||
|
const NodeID v = current_edge.second;
|
||||||
|
if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) {
|
||||||
|
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
||||||
|
++index_into_forward_path;
|
||||||
|
approximated_forward_sharing[v] = forward_heap1.GetKey(u);
|
||||||
|
} else {
|
||||||
|
//sharing (s) = sharing (t)
|
||||||
|
approximated_forward_sharing[v] = approximated_forward_sharing[u];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned index_into_reverse_path = 0;
|
||||||
|
//sweep over search space, compute backward sharing
|
||||||
|
BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) {
|
||||||
|
const NodeID u = current_edge.first;
|
||||||
|
const NodeID v = current_edge.second;
|
||||||
|
if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) {
|
||||||
|
//current_edge is on shortest path => sharing(u):=queue.GetKey(u);
|
||||||
|
++index_into_reverse_path;
|
||||||
|
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
|
||||||
|
} else {
|
||||||
|
//sharing (s) = sharing (t)
|
||||||
|
approximated_reverse_sharing[v] = approximated_reverse_sharing[u];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::vector<NodeID> nodes_that_passed_preselection;
|
||||||
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
|
BOOST_FOREACH(const NodeID node, viaNodeCandidates) {
|
||||||
if(node == middle) //subpath optimality tells us that this case is just the shortest path
|
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
|
||||||
continue;
|
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 sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA);
|
||||||
|
bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing);
|
||||||
|
|
||||||
int sharing = approximateAmountOfSharing(node, forwardHeap, backwardHeap, packedShortestPath);
|
if(lengthPassed && sharingPassed && stretchPassed) {
|
||||||
int length1 = forwardHeap->GetKey(node);
|
nodes_that_passed_preselection.push_back(node);
|
||||||
int length2 = backwardHeap->GetKey(node);
|
}
|
||||||
bool lengthPassed = (length1+length2 < _upperBound*(1+VIAPATH_EPSILON));
|
|
||||||
bool sharingPassed = (sharing <= _upperBound*VIAPATH_GAMMA);
|
|
||||||
bool stretchPassed = length1+length2 - sharing < (1.+VIAPATH_EPSILON)*(_upperBound-sharing);
|
|
||||||
|
|
||||||
if(lengthPassed && sharingPassed && stretchPassed)
|
|
||||||
nodesThatPassPreselection.push_back(std::make_pair(node, length1+length2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<NodeID> & packedShortestPath = packed_forward_path;
|
||||||
|
std::reverse(packedShortestPath.begin(), packedShortestPath.end());
|
||||||
|
packedShortestPath.push_back(middle_node);
|
||||||
|
packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end());
|
||||||
std::vector<RankedCandidateNode > rankedCandidates;
|
std::vector<RankedCandidateNode > rankedCandidates;
|
||||||
|
|
||||||
//prioritizing via nodes for deep inspection
|
//prioritizing via nodes for deep inspection
|
||||||
BOOST_FOREACH(const PreselectedNode node, nodesThatPassPreselection) {
|
BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) {
|
||||||
int lengthOfViaPath = 0, sharingOfViaPath = 0;
|
int lengthOfViaPath = 0, sharingOfViaPath = 0;
|
||||||
|
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath);
|
||||||
computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, offset, packedShortestPath);
|
if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) {
|
||||||
if(sharingOfViaPath <= VIAPATH_GAMMA*_upperBound)
|
rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath));
|
||||||
rankedCandidates.push_back(RankedCandidateNode(node.first, lengthOfViaPath, sharingOfViaPath));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(rankedCandidates.begin(), rankedCandidates.end());
|
std::sort(rankedCandidates.begin(), rankedCandidates.end());
|
||||||
|
|
||||||
NodeID selectedViaNode = UINT_MAX;
|
NodeID selectedViaNode = UINT_MAX;
|
||||||
int lengthOfViaPath = INT_MAX;
|
int lengthOfViaPath = INT_MAX;
|
||||||
NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
|
NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX;
|
||||||
BOOST_FOREACH(const RankedCandidateNode candidate, rankedCandidates){
|
BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){
|
||||||
if(viaNodeCandidatePasses_T_Test(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, candidate, offset, _upperBound, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
|
if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) {
|
||||||
// select first admissable
|
// select first admissable
|
||||||
selectedViaNode = candidate.node;
|
selectedViaNode = candidate.node;
|
||||||
break;
|
break;
|
||||||
@@ -141,15 +179,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Unpack shortest path and alternative, if they exist
|
//Unpack shortest path and alternative, if they exist
|
||||||
if(INT_MAX != _upperBound) {
|
if(INT_MAX != upper_bound_to_shortest_path_distance) {
|
||||||
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
|
super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath);
|
||||||
rawRouteData.lengthOfShortestPath = _upperBound;
|
rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
|
||||||
} else {
|
} else {
|
||||||
rawRouteData.lengthOfShortestPath = INT_MAX;
|
rawRouteData.lengthOfShortestPath = INT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedViaNode != UINT_MAX) {
|
if(selectedViaNode != UINT_MAX) {
|
||||||
retrievePackedViaPath(forwardHeap, backwardHeap, forwardHeap2, backwardHeap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
|
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, rawRouteData.computedAlternativePath);
|
||||||
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
|
rawRouteData.lengthOfAlternativePath = lengthOfViaPath;
|
||||||
} else {
|
} else {
|
||||||
rawRouteData.lengthOfAlternativePath = INT_MAX;
|
rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||||
@@ -158,7 +196,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
//unpack <s,..,v,..,t> by exploring search spaces from v
|
//unpack <s,..,v,..,t> by exploring search spaces from v
|
||||||
inline void retrievePackedViaPath(const HeapPtr & _forwardHeap1, const HeapPtr & _backwardHeap1, const HeapPtr & _forwardHeap2, const HeapPtr & _backwardHeap2,
|
inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2,
|
||||||
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
|
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) {
|
||||||
//unpack [s,v)
|
//unpack [s,v)
|
||||||
std::vector<NodeID> packed_s_v_path, packed_v_t_path;
|
std::vector<NodeID> packed_s_v_path, packed_v_t_path;
|
||||||
@@ -170,16 +208,16 @@ private:
|
|||||||
super::UnpackPath(packed_s_v_path, unpackedPath);
|
super::UnpackPath(packed_s_v_path, unpackedPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void computeLengthAndSharingOfViaPath(const PreselectedNode& node, int *lengthOfViaPath, int *sharingOfViaPath,
|
inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path,
|
||||||
const int offset, const std::vector<NodeID> & packedShortestPath) {
|
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();
|
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||||
|
|
||||||
HeapPtr & existingForwardHeap = super::_queryData.forwardHeap;
|
QueryHeap & existingForwardHeap = *super::_queryData.forwardHeap;
|
||||||
HeapPtr & existingBackwardHeap = super::_queryData.backwardHeap;
|
QueryHeap & existingBackwardHeap = *super::_queryData.backwardHeap;
|
||||||
HeapPtr & newForwardHeap = super::_queryData.forwardHeap2;
|
QueryHeap & newForwardHeap = *super::_queryData.forwardHeap2;
|
||||||
HeapPtr & newBackwardHeap = super::_queryData.backwardHeap2;
|
QueryHeap & newBackwardHeap = *super::_queryData.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;
|
||||||
@@ -189,18 +227,18 @@ private:
|
|||||||
|
|
||||||
NodeID s_v_middle = UINT_MAX;
|
NodeID s_v_middle = UINT_MAX;
|
||||||
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
|
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s
|
||||||
newBackwardHeap->Insert(node.first, 0, node.first);
|
newBackwardHeap.Insert(via_node, 0, via_node);
|
||||||
while (newBackwardHeap->Size() > 0) {
|
while (0 < newBackwardHeap.Size()) {
|
||||||
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
|
super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_v_Path, 2 * offset, false);
|
||||||
}
|
}
|
||||||
//compute path <v,..,t> by reusing backward search from node t
|
//compute path <v,..,t> by reusing backward search from node t
|
||||||
NodeID v_t_middle = UINT_MAX;
|
NodeID v_t_middle = UINT_MAX;
|
||||||
int upperBoundFor_v_t_Path = INT_MAX;
|
int upperBoundFor_v_t_Path = INT_MAX;
|
||||||
newForwardHeap->Insert(node.first, 0, node.first);
|
newForwardHeap.Insert(via_node, 0, via_node);
|
||||||
while (newForwardHeap->Size() > 0) {
|
while (0 < newForwardHeap.Size() ) {
|
||||||
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
|
super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_t_Path, 2 * offset, true);
|
||||||
}
|
}
|
||||||
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
|
*real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
|
||||||
|
|
||||||
if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
|
if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
|
||||||
return;
|
return;
|
||||||
@@ -211,35 +249,35 @@ private:
|
|||||||
|
|
||||||
//partial unpacking, compute sharing
|
//partial unpacking, compute sharing
|
||||||
//First partially unpack s-->v until paths deviate, note length of common path.
|
//First partially unpack s-->v until paths deviate, note length of common path.
|
||||||
for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packedShortestPath.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] == packedShortestPath[i] && packed_s_v_path[i + 1] == packedShortestPath[i + 1]) {
|
if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) {
|
||||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]);
|
||||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
if (packed_s_v_path[i] == packedShortestPath[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);
|
||||||
super::UnpackEdge(packedShortestPath[i], packedShortestPath[i+1], partiallyUnpackedShortestPath);
|
super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//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 QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]);
|
||||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += search_graph->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
|
||||||
int viaPathIndex = packed_v_t_path.size() - 1;
|
int viaPathIndex = packed_v_t_path.size() - 1;
|
||||||
int shortestPathIndex = packedShortestPath.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] == packedShortestPath[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packedShortestPath[shortestPathIndex]) {
|
if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) {
|
||||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]);
|
||||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
if (packed_v_t_path[viaPathIndex] == packedShortestPath[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);
|
||||||
super::UnpackEdge(packedShortestPath[shortestPathIndex-1] , packedShortestPath[shortestPathIndex], partiallyUnpackedShortestPath);
|
super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,16 +287,16 @@ 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 QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]);
|
||||||
*sharingOfViaPath += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
*sharing_of_via_path += search_graph->GetEdgeData(edgeID).distance;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//finished partial unpacking spree! Amount of sharing is stored to appropriate poiner variable
|
//finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
|
inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector<NodeID> & packedShortestPath) {
|
||||||
std::vector<NodeID> packedAlternativePath;
|
std::vector<NodeID> packedAlternativePath;
|
||||||
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
|
super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath);
|
||||||
|
|
||||||
@@ -269,9 +307,9 @@ private:
|
|||||||
int aindex = 0;
|
int aindex = 0;
|
||||||
//compute forward sharing
|
//compute forward sharing
|
||||||
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) {
|
||||||
// INFO("retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")");
|
// SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")";
|
||||||
typename QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]);
|
||||||
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
sharing += search_graph->GetEdgeData(edgeID).distance;
|
||||||
++aindex;
|
++aindex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,55 +317,65 @@ 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 QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]);
|
||||||
sharing += super::_queryData.graph->GetEdgeData(edgeID).distance;
|
sharing += search_graph->GetEdgeData(edgeID).distance;
|
||||||
--aindex; --bindex;
|
--aindex; --bindex;
|
||||||
}
|
}
|
||||||
return sharing;
|
return sharing;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AlternativeRoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection, std::vector<NodeID>& searchSpaceIntersection) const {
|
template<bool forwardDirection>
|
||||||
const NodeID node = _forwardHeap->DeleteMin();
|
inline void AlternativeRoutingStep(
|
||||||
|
QueryHeap & _forward_heap,
|
||||||
|
QueryHeap & _reverse_heap,
|
||||||
|
NodeID *middle_node,
|
||||||
|
int *upper_bound_to_shortest_path_distance,
|
||||||
|
std::vector<NodeID>& searchSpaceIntersection,
|
||||||
|
std::vector<SearchSpaceEdge> & search_space,
|
||||||
|
const int edgeBasedOffset
|
||||||
|
) const {
|
||||||
|
const NodeID node = _forward_heap.DeleteMin();
|
||||||
|
const int distance = _forward_heap.GetKey(node);
|
||||||
|
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
|
||||||
|
if(scaledDistance > *upper_bound_to_shortest_path_distance){
|
||||||
|
_forward_heap.DeleteAll();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const int distance = _forwardHeap->GetKey(node);
|
search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node));
|
||||||
if(_backwardHeap->WasInserted(node) ){
|
|
||||||
|
if(_reverse_heap.WasInserted(node) ){
|
||||||
searchSpaceIntersection.push_back(node);
|
searchSpaceIntersection.push_back(node);
|
||||||
|
|
||||||
const int newDistance = _backwardHeap->GetKey(node) + distance;
|
const int newDistance = _reverse_heap.GetKey(node) + distance;
|
||||||
if(newDistance < *_upperbound ){
|
if(newDistance < *upper_bound_to_shortest_path_distance ){
|
||||||
if(newDistance>=0 ) {
|
if(newDistance>=0 ) {
|
||||||
*middle = node;
|
*middle_node = node;
|
||||||
*_upperbound = newDistance;
|
*upper_bound_to_shortest_path_distance = newDistance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON);
|
for ( typename SearchGraph::EdgeIterator edge = search_graph->BeginEdges( node ); edge < search_graph->EndEdges(node); edge++ ) {
|
||||||
if(scaledDistance > *_upperbound){
|
const typename SearchGraph::EdgeData & data = search_graph->GetEdgeData(edge);
|
||||||
_forwardHeap->DeleteAll();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = super::_queryData.graph->BeginEdges( node ); edge < super::_queryData.graph->EndEdges(node); edge++ ) {
|
|
||||||
const typename QueryDataT::Graph::EdgeData & data = super::_queryData.graph->GetEdgeData(edge);
|
|
||||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
||||||
if(forwardDirectionFlag) {
|
if(forwardDirectionFlag) {
|
||||||
|
|
||||||
const NodeID to = super::_queryData.graph->GetTarget(edge);
|
const NodeID to = search_graph->GetTarget(edge);
|
||||||
const int edgeWeight = data.distance;
|
const int edgeWeight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
const int toDistance = distance + edgeWeight;
|
const int toDistance = distance + edgeWeight;
|
||||||
|
|
||||||
//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, toDistance, node );
|
||||||
|
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
|
else if ( toDistance < _forward_heap.GetKey( to ) ) {
|
||||||
_forwardHeap->GetData( to ).parent = node;
|
_forward_heap.GetData( to ).parent = node;
|
||||||
_forwardHeap->DecreaseKey( to, toDistance );
|
_forward_heap.DecreaseKey( to, toDistance );
|
||||||
//new parent
|
//new parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,16 +383,17 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//conduct T-Test
|
//conduct T-Test
|
||||||
inline bool viaNodeCandidatePasses_T_Test( HeapPtr& existingForwardHeap, HeapPtr& existingBackwardHeap, HeapPtr& newForwardHeap, HeapPtr& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
|
inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) {
|
||||||
|
newForwardHeap.Clear();
|
||||||
|
newBackwardHeap.Clear();
|
||||||
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;
|
||||||
|
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
|
||||||
*s_v_middle = UINT_MAX;
|
*s_v_middle = UINT_MAX;
|
||||||
int upperBoundFor_s_v_Path = INT_MAX;
|
int upperBoundFor_s_v_Path = INT_MAX;
|
||||||
//compute path <s,..,v> by reusing forward search from s
|
//compute path <s,..,v> by reusing forward search from s
|
||||||
newBackwardHeap->Insert(candidate.node, 0, candidate.node);
|
newBackwardHeap.Insert(candidate.node, 0, candidate.node);
|
||||||
while (newBackwardHeap->Size() > 0) {
|
while (newBackwardHeap.Size() > 0) {
|
||||||
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
|
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,8 +403,8 @@ private:
|
|||||||
//compute path <v,..,t> by reusing backward search from t
|
//compute path <v,..,t> by reusing backward search from t
|
||||||
*v_t_middle = UINT_MAX;
|
*v_t_middle = UINT_MAX;
|
||||||
int upperBoundFor_v_t_Path = INT_MAX;
|
int upperBoundFor_v_t_Path = INT_MAX;
|
||||||
newForwardHeap->Insert(candidate.node, 0, candidate.node);
|
newForwardHeap.Insert(candidate.node, 0, candidate.node);
|
||||||
while (newForwardHeap->Size() > 0) {
|
while (newForwardHeap.Size() > 0) {
|
||||||
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
|
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,14 +418,21 @@ private:
|
|||||||
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path);
|
super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path);
|
||||||
|
|
||||||
NodeID s_P = *s_v_middle, t_P = *v_t_middle;
|
NodeID s_P = *s_v_middle, t_P = *v_t_middle;
|
||||||
|
if(UINT_MAX == s_P) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(UINT_MAX == t_P) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
|
const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath;
|
||||||
int unpackedUntilDistance = 0;
|
int unpackedUntilDistance = 0;
|
||||||
|
|
||||||
std::stack<UnpackEdge> 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 QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]);
|
||||||
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
|
int lengthOfCurrentEdge = search_graph->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 {
|
||||||
@@ -386,17 +442,17 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!unpackStack.empty()) {
|
while (!unpackStack.empty()) {
|
||||||
const UnpackEdge viaPathEdge = unpackStack.top();
|
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
||||||
unpackStack.pop();
|
unpackStack.pop();
|
||||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||||
if(UINT_MAX == edgeIDInViaPath)
|
if(UINT_MAX == edgeIDInViaPath)
|
||||||
return false;
|
return false;
|
||||||
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
|
typename SearchGraph::EdgeData currentEdgeData = search_graph->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 QueryDataT::Graph::EdgeIterator edgeIDOfSecondSegment = super::_queryData.graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
typename SearchGraph::EdgeIterator edgeIDOfSecondSegment = search_graph->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second);
|
||||||
int lengthOfSecondSegment = super::_queryData.graph->GetEdgeData(edgeIDOfSecondSegment).distance;
|
int lengthOfSecondSegment = search_graph->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) {
|
||||||
@@ -416,8 +472,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 QueryDataT::Graph::EdgeIterator edgeID = super::_queryData.graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
typename SearchGraph::EdgeIterator edgeID = search_graph->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]);
|
||||||
int lengthOfCurrentEdge = super::_queryData.graph->GetEdgeData(edgeID).distance;
|
int lengthOfCurrentEdge = search_graph->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 {
|
||||||
@@ -427,17 +483,17 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!unpackStack.empty()) {
|
while (!unpackStack.empty()) {
|
||||||
const UnpackEdge viaPathEdge = unpackStack.top();
|
const SearchSpaceEdge viaPathEdge = unpackStack.top();
|
||||||
unpackStack.pop();
|
unpackStack.pop();
|
||||||
typename QueryDataT::Graph::EdgeIterator edgeIDInViaPath = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
typename SearchGraph::EdgeIterator edgeIDInViaPath = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second);
|
||||||
if(UINT_MAX == edgeIDInViaPath)
|
if(UINT_MAX == edgeIDInViaPath)
|
||||||
return false;
|
return false;
|
||||||
typename QueryDataT::Graph::EdgeData currentEdgeData = super::_queryData.graph->GetEdgeData(edgeIDInViaPath);
|
typename SearchGraph::EdgeData currentEdgeData = search_graph->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 QueryDataT::Graph::EdgeIterator edgeIDOfFirstSegment = super::_queryData.graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
typename SearchGraph::EdgeIterator edgeIDOfFirstSegment = search_graph->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath);
|
||||||
int lengthOfFirstSegment = super::_queryData.graph->GetEdgeData( edgeIDOfFirstSegment).distance;
|
int lengthOfFirstSegment = search_graph->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));
|
||||||
@@ -454,20 +510,21 @@ 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.
|
||||||
HeapPtr& forwardHeap = super::_queryData.forwardHeap3;
|
|
||||||
HeapPtr& backwardHeap = super::_queryData.backwardHeap3;
|
|
||||||
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
||||||
|
|
||||||
|
QueryHeap& forward_heap3 = *super::_queryData.forwardHeap3;
|
||||||
|
QueryHeap& backward_heap3 = *super::_queryData.backwardHeap3;
|
||||||
int _upperBound = INT_MAX;
|
int _upperBound = INT_MAX;
|
||||||
NodeID middle = UINT_MAX;
|
NodeID middle = UINT_MAX;
|
||||||
forwardHeap->Insert(s_P, 0, s_P);
|
forward_heap3.Insert(s_P, 0, s_P);
|
||||||
backwardHeap->Insert(t_P, 0, t_P);
|
backward_heap3.Insert(t_P, 0, t_P);
|
||||||
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
//exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath
|
||||||
while (forwardHeap->Size() + backwardHeap->Size() > 0) {
|
while (forward_heap3.Size() + backward_heap3.Size() > 0) {
|
||||||
if (forwardHeap->Size() > 0) {
|
if (forward_heap3.Size() > 0) {
|
||||||
super::RoutingStep(forwardHeap, backwardHeap, &middle, &_upperBound, offset, true);
|
super::RoutingStep(forward_heap3, backward_heap3, &middle, &_upperBound, offset, true);
|
||||||
}
|
}
|
||||||
if (backwardHeap->Size() > 0) {
|
if (backward_heap3.Size() > 0) {
|
||||||
super::RoutingStep(backwardHeap, forwardHeap, &middle, &_upperBound, offset, false);
|
super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (_upperBound <= lengthOfPathT_Test_Path);
|
return (_upperBound <= lengthOfPathT_Test_Path);
|
||||||
|
|||||||
@@ -23,43 +23,47 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef BASICROUTINGINTERFACE_H_
|
#ifndef BASICROUTINGINTERFACE_H_
|
||||||
#define BASICROUTINGINTERFACE_H_
|
#define BASICROUTINGINTERFACE_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/RawRouteData.h"
|
||||||
|
#include "../Util/ContainerUtils.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "../Plugins/RawRouteData.h"
|
#include <stack>
|
||||||
|
|
||||||
template<class QueryDataT>
|
template<class QueryDataT>
|
||||||
class BasicRoutingInterface {
|
class BasicRoutingInterface : boost::noncopyable{
|
||||||
protected:
|
protected:
|
||||||
QueryDataT & _queryData;
|
QueryDataT & _queryData;
|
||||||
public:
|
public:
|
||||||
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
|
BasicRoutingInterface(QueryDataT & qd) : _queryData(qd) { }
|
||||||
virtual ~BasicRoutingInterface(){ };
|
virtual ~BasicRoutingInterface(){ };
|
||||||
|
|
||||||
inline void RoutingStep(typename QueryDataT::HeapPtr & _forwardHeap, typename QueryDataT::HeapPtr & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
||||||
const NodeID node = _forwardHeap->DeleteMin();
|
const NodeID node = _forwardHeap.DeleteMin();
|
||||||
const int distance = _forwardHeap->GetKey(node);
|
const int distance = _forwardHeap.GetKey(node);
|
||||||
// INFO((forwardDirection ? "[forw]" : "[back]") << " settled node " << node << " at distance " << distance);
|
//SimpleLogger().Write() << "Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance;
|
||||||
if(_backwardHeap->WasInserted(node) ){
|
if(_backwardHeap.WasInserted(node) ){
|
||||||
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanned node " << node << " in both directions, upper bound: " << *_upperbound);
|
const int newDistance = _backwardHeap.GetKey(node) + distance;
|
||||||
const int newDistance = _backwardHeap->GetKey(node) + distance;
|
|
||||||
if(newDistance < *_upperbound ){
|
if(newDistance < *_upperbound ){
|
||||||
if(newDistance>=0 ) {
|
if(newDistance>=0 ) {
|
||||||
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> node " << node << " is new middle at total distance " << newDistance);
|
|
||||||
*middle = node;
|
*middle = node;
|
||||||
*_upperbound = newDistance;
|
*_upperbound = newDistance;
|
||||||
} else {
|
} else {
|
||||||
// INFO((forwardDirection ? "[forw]" : "[back]") << " -> ignored " << node << " as new middle at total distance " << newDistance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(distance-edgeBasedOffset > *_upperbound){
|
if(distance-edgeBasedOffset > *_upperbound){
|
||||||
_forwardHeap->DeleteAll();
|
_forwardHeap.DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) {
|
//Stalling
|
||||||
|
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
||||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
||||||
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
|
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
|
||||||
if(backwardDirectionFlag) {
|
if(backwardDirectionFlag) {
|
||||||
@@ -68,16 +72,15 @@ public:
|
|||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
|
|
||||||
//Stalling
|
if(_forwardHeap.WasInserted( to )) {
|
||||||
if(_forwardHeap->WasInserted( to )) {
|
if(_forwardHeap.GetKey( to ) + edgeWeight < distance) {
|
||||||
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); edge++ ) {
|
for ( typename QueryDataT::Graph::EdgeIterator edge = _queryData.graph->BeginEdges( node ); edge < _queryData.graph->EndEdges(node); ++edge ) {
|
||||||
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
const typename QueryDataT::Graph::EdgeData & data = _queryData.graph->GetEdgeData(edge);
|
||||||
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
||||||
if(forwardDirectionFlag) {
|
if(forwardDirectionFlag) {
|
||||||
@@ -89,23 +92,20 @@ public:
|
|||||||
const int toDistance = distance + edgeWeight;
|
const int toDistance = distance + edgeWeight;
|
||||||
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !_forwardHeap->WasInserted( to ) ) {
|
if ( !_forwardHeap.WasInserted( to ) ) {
|
||||||
// INFO((forwardDirection ? "[forw]" : "[back]") << " scanning edge (" << node << "," << to << ") with distance " << toDistance << ", edge length: " << data.distance);
|
_forwardHeap.Insert( to, toDistance, node );
|
||||||
_forwardHeap->Insert( to, toDistance, node );
|
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
|
else if ( toDistance < _forwardHeap.GetKey( to ) ) {
|
||||||
// INFO((forwardDirection ? "[forw]" : "[back]") << " decrease and scanning edge (" << node << "," << to << ") from " << _forwardHeap->GetKey(to) << "to " << toDistance << ", edge length: " << data.distance);
|
_forwardHeap.GetData( to ).parent = node;
|
||||||
_forwardHeap->GetData( to ).parent = node;
|
_forwardHeap.DecreaseKey( to, toDistance );
|
||||||
_forwardHeap->DecreaseKey( to, toDistance );
|
|
||||||
//new parent
|
//new parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackPath(std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
|
inline void UnpackPath(const std::vector<NodeID> & packedPath, std::vector<_PathData> & unpackedPath) const {
|
||||||
|
|
||||||
const unsigned sizeOfPackedPath = packedPath.size();
|
const unsigned sizeOfPackedPath = packedPath.size();
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
||||||
|
|
||||||
@@ -118,15 +118,12 @@ public:
|
|||||||
while(!recursionStack.empty()) {
|
while(!recursionStack.empty()) {
|
||||||
edge = recursionStack.top();
|
edge = recursionStack.top();
|
||||||
recursionStack.pop();
|
recursionStack.pop();
|
||||||
// INFO("Unpacking edge (" << edge.first << "," << edge.second << ")");
|
|
||||||
|
|
||||||
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
||||||
int smallestWeight = INT_MAX;
|
int smallestWeight = INT_MAX;
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
||||||
// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")");
|
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){
|
||||||
// INFO("1smallest " << eit << ", " << weight);
|
|
||||||
smallestEdge = eit;
|
smallestEdge = eit;
|
||||||
smallestWeight = weight;
|
smallestWeight = weight;
|
||||||
}
|
}
|
||||||
@@ -135,9 +132,7 @@ public:
|
|||||||
if(smallestEdge == SPECIAL_EDGEID){
|
if(smallestEdge == SPECIAL_EDGEID){
|
||||||
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.second);eit < _queryData.graph->EndEdges(edge.second);++eit){
|
||||||
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
const int weight = _queryData.graph->GetEdgeData(eit).distance;
|
||||||
// INFO("Checking edge (" << edge.first << "/" << _queryData.graph->GetTarget(eit) << ")");
|
|
||||||
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
if(_queryData.graph->GetTarget(eit) == edge.first && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).backward){
|
||||||
// INFO("2smallest " << eit << ", " << weight);
|
|
||||||
smallestEdge = eit;
|
smallestEdge = eit;
|
||||||
smallestWeight = weight;
|
smallestWeight = weight;
|
||||||
}
|
}
|
||||||
@@ -159,7 +154,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
|
inline void UnpackEdge(const NodeID s, const NodeID t, std::vector<NodeID> & unpackedPath) const {
|
||||||
|
|
||||||
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
std::stack<std::pair<NodeID, NodeID> > recursionStack;
|
||||||
recursionStack.push(std::make_pair(s,t));
|
recursionStack.push(std::make_pair(s,t));
|
||||||
|
|
||||||
@@ -193,7 +187,6 @@ public:
|
|||||||
if(ed.shortcut) {//unpack
|
if(ed.shortcut) {//unpack
|
||||||
const NodeID middle = ed.id;
|
const NodeID middle = ed.id;
|
||||||
//again, we need to this in reversed order
|
//again, we need to this in reversed order
|
||||||
// INFO("unpacking (" << middle << "," << edge.second << ") and (" << edge.first << "," << middle << ")");
|
|
||||||
recursionStack.push(std::make_pair(middle, edge.second));
|
recursionStack.push(std::make_pair(middle, edge.second));
|
||||||
recursionStack.push(std::make_pair(edge.first, middle));
|
recursionStack.push(std::make_pair(edge.first, middle));
|
||||||
} else {
|
} else {
|
||||||
@@ -204,22 +197,29 @@ public:
|
|||||||
unpackedPath.push_back(t);
|
unpackedPath.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void RetrievePackedPathFromHeap(const typename QueryDataT::HeapPtr & _fHeap, const typename QueryDataT::HeapPtr & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) {
|
inline void RetrievePackedPathFromHeap(typename QueryDataT::QueryHeap & _fHeap, typename QueryDataT::QueryHeap & _bHeap, const NodeID middle, std::vector<NodeID>& packedPath) const {
|
||||||
NodeID pathNode = middle;
|
NodeID pathNode = middle;
|
||||||
while(pathNode != _fHeap->GetData(pathNode).parent) {
|
while(pathNode != _fHeap.GetData(pathNode).parent) {
|
||||||
pathNode = _fHeap->GetData(pathNode).parent;
|
pathNode = _fHeap.GetData(pathNode).parent;
|
||||||
packedPath.push_back(pathNode);
|
packedPath.push_back(pathNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::reverse(packedPath.begin(), packedPath.end());
|
std::reverse(packedPath.begin(), packedPath.end());
|
||||||
|
|
||||||
packedPath.push_back(middle);
|
packedPath.push_back(middle);
|
||||||
pathNode = middle;
|
pathNode = middle;
|
||||||
while (pathNode != _bHeap->GetData(pathNode).parent){
|
while (pathNode != _bHeap.GetData(pathNode).parent){
|
||||||
pathNode = _bHeap->GetData(pathNode).parent;
|
pathNode = _bHeap.GetData(pathNode).parent;
|
||||||
packedPath.push_back(pathNode);
|
packedPath.push_back(pathNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void RetrievePackedPathFromSingleHeap(typename QueryDataT::QueryHeap & search_heap, const NodeID middle, std::vector<NodeID>& packed_path) const {
|
||||||
|
NodeID pathNode = middle;
|
||||||
|
while(pathNode != search_heap.GetData(pathNode).parent) {
|
||||||
|
pathNode = search_heap.GetData(pathNode).parent;
|
||||||
|
packed_path.push_back(pathNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,13 +28,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
template<class QueryDataT>
|
template<class QueryDataT>
|
||||||
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
|
class ShortestPathRouting : public BasicRoutingInterface<QueryDataT>{
|
||||||
typedef BasicRoutingInterface<QueryDataT> super;
|
typedef BasicRoutingInterface<QueryDataT> super;
|
||||||
|
typedef typename QueryDataT::QueryHeap QueryHeap;
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting(QueryDataT & qd) : super(qd) {}
|
ShortestPathRouting( QueryDataT & qd) : super(qd) {}
|
||||||
|
|
||||||
~ShortestPathRouting() {}
|
~ShortestPathRouting() {}
|
||||||
|
|
||||||
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) {
|
void operator()(std::vector<PhantomNodes> & phantomNodesVector, RawRouteData & rawRouteData) const {
|
||||||
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
|
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
||||||
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX()) {
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
@@ -43,125 +44,108 @@ public:
|
|||||||
int distance1 = 0;
|
int distance1 = 0;
|
||||||
int distance2 = 0;
|
int distance2 = 0;
|
||||||
|
|
||||||
bool searchFrom1stStartNode(true);
|
bool searchFrom1stStartNode = true;
|
||||||
bool searchFrom2ndStartNode(true);
|
bool searchFrom2ndStartNode = true;
|
||||||
NodeID middle1 = ( NodeID ) UINT_MAX;
|
NodeID middle1 = UINT_MAX;
|
||||||
NodeID middle2 = ( NodeID ) UINT_MAX;
|
NodeID middle2 = UINT_MAX;
|
||||||
std::vector<NodeID> packedPath1;
|
std::vector<NodeID> packedPath1;
|
||||||
std::vector<NodeID> packedPath2;
|
std::vector<NodeID> packedPath2;
|
||||||
|
|
||||||
typename QueryDataT::HeapPtr & forwardHeap = super::_queryData.forwardHeap;
|
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
||||||
typename QueryDataT::HeapPtr & backwardHeap = super::_queryData.backwardHeap;
|
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
||||||
|
super::_queryData.InitializeOrClearThirdThreadLocalStorage();
|
||||||
typename QueryDataT::HeapPtr & forwardHeap2 = super::_queryData.forwardHeap2;
|
|
||||||
typename QueryDataT::HeapPtr & backwardHeap2 = super::_queryData.backwardHeap2;
|
|
||||||
|
|
||||||
|
QueryHeap & forward_heap1 = *(super::_queryData.forwardHeap);
|
||||||
|
QueryHeap & reverse_heap1 = *(super::_queryData.backwardHeap);
|
||||||
|
QueryHeap & forward_heap2 = *(super::_queryData.forwardHeap2);
|
||||||
|
QueryHeap & reverse_heap2 = *(super::_queryData.backwardHeap2);
|
||||||
|
|
||||||
//Get distance to next pair of target nodes.
|
//Get distance to next pair of target nodes.
|
||||||
BOOST_FOREACH(PhantomNodes & phantomNodePair, phantomNodesVector) {
|
BOOST_FOREACH(const PhantomNodes & phantomNodePair, phantomNodesVector) {
|
||||||
super::_queryData.InitializeOrClearFirstThreadLocalStorage();
|
forward_heap1.Clear(); forward_heap2.Clear();
|
||||||
super::_queryData.InitializeOrClearSecondThreadLocalStorage();
|
reverse_heap1.Clear(); reverse_heap2.Clear();
|
||||||
|
|
||||||
int _localUpperbound1 = INT_MAX;
|
int _localUpperbound1 = INT_MAX;
|
||||||
int _localUpperbound2 = INT_MAX;
|
int _localUpperbound2 = INT_MAX;
|
||||||
|
|
||||||
|
middle1 = 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(searchFrom1stStartNode) {
|
||||||
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||||
forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
// INFO("a 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode << " with weight " << phantomNodePair.startPhantom.weight1);
|
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||||
// } else {
|
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
// INFO("Skipping first start node");
|
}
|
||||||
}
|
|
||||||
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
||||||
forwardHeap->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||||
forwardHeap2->Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
// INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
// INFO("b 1,2)forw insert " << phantomNodePair.startPhantom.edgeBasedNode+1 << " with weight " << -phantomNodePair.startPhantom.weight1);
|
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||||
// } else if(!searchFrom2ndStartNode) {
|
// INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
// INFO("Skipping second start node");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// backwardHeap->Clear();
|
|
||||||
// backwardHeap2->Clear();
|
|
||||||
//insert new backward nodes into backward heap, unadjusted.
|
//insert new backward nodes into backward heap, unadjusted.
|
||||||
backwardHeap->Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
||||||
// INFO("1) back insert " << phantomNodePair.targetPhantom.edgeBasedNode << " with weight " << phantomNodePair.targetPhantom.weight1);
|
// INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
||||||
// INFO("2) back insert " << phantomNodePair.targetPhantom.edgeBasedNode+1 << " with weight " << phantomNodePair.targetPhantom.weight2);
|
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
||||||
backwardHeap2->Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
// INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
|
||||||
}
|
}
|
||||||
int offset = (phantomNodePair.startPhantom.isBidirected() ? std::max(phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.weight2) : phantomNodePair.startPhantom.weight1) ;
|
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
||||||
offset += (phantomNodePair.targetPhantom.isBidirected() ? std::max(phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.weight2) : phantomNodePair.targetPhantom.weight1) ;
|
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
||||||
|
|
||||||
//run two-Target Dijkstra routing step.
|
//run two-Target Dijkstra routing step.
|
||||||
while(forwardHeap->Size() + backwardHeap->Size() > 0){
|
while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){
|
||||||
if(forwardHeap->Size() > 0){
|
if(0 < forward_heap1.Size()){
|
||||||
super::RoutingStep(forwardHeap, backwardHeap, &middle1, &_localUpperbound1, 2*offset, true);
|
super::RoutingStep(forward_heap1, reverse_heap1, &middle1, &_localUpperbound1, forward_offset, true);
|
||||||
}
|
}
|
||||||
if(backwardHeap->Size() > 0){
|
if(0 < reverse_heap1.Size() ){
|
||||||
super::RoutingStep(backwardHeap, forwardHeap, &middle1, &_localUpperbound1, 2*offset, false);
|
super::RoutingStep(reverse_heap1, forward_heap1, &middle1, &_localUpperbound1, reverse_offset, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(backwardHeap2->Size() > 0) {
|
if(0 < reverse_heap2.Size()) {
|
||||||
while(forwardHeap2->Size() + backwardHeap2->Size() > 0){
|
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||||
if(forwardHeap2->Size() > 0){
|
if(0 < forward_heap2.Size()){
|
||||||
super::RoutingStep(forwardHeap2, backwardHeap2, &middle2, &_localUpperbound2, 2*offset, true);
|
super::RoutingStep(forward_heap2, reverse_heap2, &middle2, &_localUpperbound2, forward_offset, true);
|
||||||
}
|
}
|
||||||
if(backwardHeap2->Size() > 0){
|
if(0 < reverse_heap2.Size()){
|
||||||
super::RoutingStep(backwardHeap2, forwardHeap2, &middle2, &_localUpperbound2, 2*offset, false);
|
super::RoutingStep(reverse_heap2, forward_heap2, &middle2, &_localUpperbound2, reverse_offset, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INFO("upperbound1: " << _localUpperbound1 << ", distance1: " << distance1);
|
|
||||||
// INFO("upperbound2: " << _localUpperbound2 << ", distance2: " << distance2);
|
|
||||||
|
|
||||||
//No path found for both target nodes?
|
//No path found for both target nodes?
|
||||||
if(INT_MAX == _localUpperbound1 && INT_MAX == _localUpperbound2) {
|
if((INT_MAX == _localUpperbound1) && (INT_MAX == _localUpperbound2)) {
|
||||||
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle1) {
|
if(UINT_MAX == middle1) {
|
||||||
searchFrom1stStartNode = false;
|
searchFrom1stStartNode = false;
|
||||||
// INFO("Next Search will not start from 1st");
|
|
||||||
} else {
|
|
||||||
// INFO("Next Search will start from 1st");
|
|
||||||
searchFrom1stStartNode = true;
|
|
||||||
}
|
}
|
||||||
if(UINT_MAX == middle2) {
|
if(UINT_MAX == middle2) {
|
||||||
searchFrom2ndStartNode = false;
|
searchFrom2ndStartNode = false;
|
||||||
// INFO("Next Search will not start from 2nd");
|
|
||||||
} else {
|
|
||||||
searchFrom2ndStartNode = true;
|
|
||||||
// INFO("Next Search will start from 2nd");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//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));
|
assert(!(INT_MAX == distance1 && INT_MAX == distance2));
|
||||||
|
|
||||||
// INFO("middle1: " << middle1);
|
|
||||||
|
|
||||||
//Unpack paths if they exist
|
//Unpack paths if they exist
|
||||||
std::vector<NodeID> temporaryPackedPath1;
|
std::vector<NodeID> temporaryPackedPath1;
|
||||||
std::vector<NodeID> temporaryPackedPath2;
|
std::vector<NodeID> temporaryPackedPath2;
|
||||||
if(INT_MAX != _localUpperbound1) {
|
if(INT_MAX != _localUpperbound1) {
|
||||||
super::RetrievePackedPathFromHeap(forwardHeap, backwardHeap, middle1, temporaryPackedPath1);
|
super::RetrievePackedPathFromHeap(forward_heap1, reverse_heap1, middle1, temporaryPackedPath1);
|
||||||
// INFO("temporaryPackedPath1 ends with " << *(temporaryPackedPath1.end()-1) );
|
|
||||||
}
|
}
|
||||||
// INFO("middle2: " << middle2);
|
|
||||||
|
|
||||||
if(INT_MAX != _localUpperbound2) {
|
if(INT_MAX != _localUpperbound2) {
|
||||||
super::RetrievePackedPathFromHeap(forwardHeap2, backwardHeap2, middle2, temporaryPackedPath2);
|
super::RetrievePackedPathFromHeap(forward_heap2, reverse_heap2, middle2, temporaryPackedPath2);
|
||||||
// INFO("temporaryPackedPath2 ends with " << *(temporaryPackedPath2.end()-1) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//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(0 == temporaryPackedPath1.size()) {
|
||||||
// INFO("Deleting path 1");
|
|
||||||
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
temporaryPackedPath1.insert(temporaryPackedPath1.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
||||||
_localUpperbound1 = _localUpperbound2;
|
_localUpperbound1 = _localUpperbound2;
|
||||||
}
|
}
|
||||||
if(0 == temporaryPackedPath2.size()) {
|
if(0 == temporaryPackedPath2.size()) {
|
||||||
// INFO("Deleting path 2");
|
|
||||||
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
temporaryPackedPath2.insert(temporaryPackedPath2.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end());
|
||||||
_localUpperbound2 = _localUpperbound1;
|
_localUpperbound2 = _localUpperbound1;
|
||||||
}
|
}
|
||||||
@@ -170,28 +154,21 @@ public:
|
|||||||
|
|
||||||
//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(0 < packedPath1.size() && 0 < packedPath2.size() ) {
|
||||||
// INFO("Both paths are non-empty");
|
|
||||||
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
|
if( *(temporaryPackedPath1.begin()) == *(temporaryPackedPath2.begin())) {
|
||||||
// INFO("both paths start with the same node:" << *(temporaryPackedPath1.begin()));
|
|
||||||
//both new route segments start with the same node, thus one of the packedPath must go.
|
//both new route segments start with the same node, thus one of the packedPath must go.
|
||||||
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
|
assert( (packedPath1.size() == packedPath2.size() ) || (*(packedPath1.end()-1) != *(packedPath2.end()-1)) );
|
||||||
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
|
if( *(packedPath1.end()-1) == *(temporaryPackedPath1.begin())) {
|
||||||
// INFO("Deleting packedPath2 that ends with " << *(packedPath2.end()-1) << ", other ends with " << *(packedPath1.end()-1));
|
|
||||||
packedPath2.clear();
|
packedPath2.clear();
|
||||||
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
|
packedPath2.insert(packedPath2.end(), packedPath1.begin(), packedPath1.end());
|
||||||
distance2 = distance1;
|
distance2 = distance1;
|
||||||
// INFO("packedPath2 now ends with " << *(packedPath2.end()-1));
|
|
||||||
} else {
|
} else {
|
||||||
// INFO("Deleting path1 that ends with " << *(packedPath1.end()-1) << ", other ends with " << *(packedPath2.end()-1));
|
|
||||||
packedPath1.clear();
|
packedPath1.clear();
|
||||||
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
|
packedPath1.insert(packedPath1.end(), packedPath2.begin(), packedPath2.end());
|
||||||
distance1 = distance2;
|
distance1 = distance2;
|
||||||
// INFO("Path1 now ends with " << *(packedPath1.end()-1));
|
|
||||||
}
|
}
|
||||||
} 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(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) {
|
||||||
// INFO("Switching");
|
|
||||||
packedPath1.swap(packedPath2);
|
packedPath1.swap(packedPath2);
|
||||||
std::swap(distance1, distance2);
|
std::swap(distance1, distance2);
|
||||||
}
|
}
|
||||||
@@ -201,61 +178,24 @@ public:
|
|||||||
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
packedPath2.insert(packedPath2.end(), temporaryPackedPath2.begin(), temporaryPackedPath2.end());
|
||||||
|
|
||||||
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
|
if( (packedPath1.back() == packedPath2.back()) && phantomNodePair.targetPhantom.isBidirected() ) {
|
||||||
// INFO("both paths end in same direction on bidirected edge, make sure start only start with : " << packedPath1.back());
|
|
||||||
|
|
||||||
NodeID lastNodeID = packedPath2.back();
|
NodeID lastNodeID = packedPath2.back();
|
||||||
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
|
searchFrom1stStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode+1);
|
||||||
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
|
searchFrom2ndStartNode &= !(lastNodeID == phantomNodePair.targetPhantom.edgeBasedNode);
|
||||||
// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode << ": " << (searchFrom1stStartNode ? "yes" : "no") );
|
|
||||||
// INFO("Next search from node " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ": " << (searchFrom2ndStartNode ? "yes" : "no") );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
distance1 += _localUpperbound1;
|
distance1 += _localUpperbound1;
|
||||||
distance2 += _localUpperbound2;
|
distance2 += _localUpperbound2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INFO("length path1: " << distance1);
|
if(distance1 > distance2){
|
||||||
// INFO("length path2: " << distance2);
|
|
||||||
if(distance1 <= distance2){
|
|
||||||
//remove consecutive duplicates
|
|
||||||
// std::cout << "unclean 1: ";
|
|
||||||
// for(unsigned i = 0; i < packedPath1.size(); ++i)
|
|
||||||
// std::cout << packedPath1[i] << " ";
|
|
||||||
// std::cout << std::endl;
|
|
||||||
|
|
||||||
// std::cout << "cleaned 1: ";
|
|
||||||
// for(unsigned i = 0; i < packedPath1.size(); ++i)
|
|
||||||
// std::cout << packedPath1[i] << " ";
|
|
||||||
// std::cout << std::endl;
|
|
||||||
// super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
|
||||||
} else {
|
|
||||||
std::swap(packedPath1, packedPath2);
|
std::swap(packedPath1, packedPath2);
|
||||||
// std::cout << "unclean 2: ";
|
|
||||||
// for(unsigned i = 0; i < packedPath2.size(); ++i)
|
|
||||||
// std::cout << packedPath2[i] << " ";
|
|
||||||
// std::cout << std::endl;
|
|
||||||
// _RemoveConsecutiveDuplicatesFromContainer(packedPath2);
|
|
||||||
// std::cout << "cleaned 2: ";
|
|
||||||
// for(unsigned i = 0; i < packedPath2.size(); ++i)
|
|
||||||
// std::cout << packedPath2[i] << " ";
|
|
||||||
// std::cout << std::endl;
|
|
||||||
// super::UnpackPath(packedPath2, unpackedPath);
|
|
||||||
}
|
}
|
||||||
_RemoveConsecutiveDuplicatesFromContainer(packedPath1);
|
remove_consecutive_duplicates_from_vector(packedPath1);
|
||||||
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
super::UnpackPath(packedPath1, rawRouteData.computedShortestPath);
|
||||||
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
|
rawRouteData.lengthOfShortestPath = std::min(distance1, distance2);
|
||||||
// INFO("Found via route with distance " << std::min(distance1, distance2));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
template<class ContainerT>
|
|
||||||
void _RemoveConsecutiveDuplicatesFromContainer(ContainerT & packedPath) {
|
|
||||||
//remove consecutive duplicates
|
|
||||||
typename ContainerT::iterator it;
|
|
||||||
// using default comparison:
|
|
||||||
it = std::unique(packedPath.begin(), packedPath.end());
|
|
||||||
packedPath.resize(it - packedPath.begin());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SHORTESTPATHROUTING_H_ */
|
#endif /* SHORTESTPATHROUTING_H_ */
|
||||||
|
|||||||
-299
@@ -1,299 +0,0 @@
|
|||||||
#Sconstruct
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
from subprocess import call
|
|
||||||
|
|
||||||
def CheckBoost(context, version):
|
|
||||||
# Boost versions are in format major.minor.subminor
|
|
||||||
v_arr = version.split(".")
|
|
||||||
version_n = 0
|
|
||||||
if len(v_arr) > 0:
|
|
||||||
version_n += int(v_arr[0])*100000
|
|
||||||
if len(v_arr) > 1:
|
|
||||||
version_n += int(v_arr[1])*100
|
|
||||||
if len(v_arr) > 2:
|
|
||||||
version_n += int(v_arr[2])
|
|
||||||
|
|
||||||
context.Message('Checking for Boost version >= %s... ' % (version))
|
|
||||||
ret = context.TryRun("""
|
|
||||||
#include <boost/version.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return BOOST_VERSION >= %d ? 0 : 1;
|
|
||||||
}
|
|
||||||
""" % version_n, '.cpp')[0]
|
|
||||||
context.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckProtobuf(context, version):
|
|
||||||
# Protobuf versions are in format major.minor.subminor
|
|
||||||
v_arr = version.split(".")
|
|
||||||
version_n = 0
|
|
||||||
if len(v_arr) > 0:
|
|
||||||
version_n += int(v_arr[0])*1000000
|
|
||||||
if len(v_arr) > 1:
|
|
||||||
version_n += int(v_arr[1])*1000
|
|
||||||
if len(v_arr) > 2:
|
|
||||||
version_n += int(v_arr[2])
|
|
||||||
|
|
||||||
context.Message('Checking for Protobuffer version >= %s... ' % (version))
|
|
||||||
ret = context.TryRun("""
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
int main() {
|
|
||||||
return (GOOGLE_PROTOBUF_VERSION >= %d) ? 0 : 1;
|
|
||||||
}
|
|
||||||
""" % version_n, '.cpp')[0]
|
|
||||||
context.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# Adding various options to the SConstruct
|
|
||||||
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
|
|
||||||
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
|
|
||||||
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
|
|
||||||
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
|
|
||||||
AddOption('--all-flags', dest='allflags', type='string', nargs=0, action='store', metavar='STRING', help='turn off -march optimization in release mode')
|
|
||||||
AddOption('--with-tools', dest='withtools', type='string', nargs=0, action='store', metavar='STRING', help='build tools for data analysis')
|
|
||||||
AddOption('--no-march', dest='nomarch', type='string', nargs=0, action='store', metavar='STRING', help='turn off native optimizations')
|
|
||||||
|
|
||||||
env = Environment( ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
|
|
||||||
env["CC"] = os.getenv("CC") or env["CC"]
|
|
||||||
env["CXX"] = os.getenv("CXX") or env["CXX"]
|
|
||||||
env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_"))
|
|
||||||
try:
|
|
||||||
env['ENV']['TERM'] = os.environ['TERM']
|
|
||||||
except KeyError:
|
|
||||||
env['ENV']['TERM'] = 'none'
|
|
||||||
|
|
||||||
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
|
|
||||||
|
|
||||||
if GetOption('cxx') is None:
|
|
||||||
#default Compiler
|
|
||||||
if sys.platform == 'darwin': #Mac OS X
|
|
||||||
env['CXX'] = 'clang++'
|
|
||||||
print 'Using default C++ Compiler: ', env['CXX'].strip()
|
|
||||||
else:
|
|
||||||
env.Replace(CXX = GetOption('cxx'))
|
|
||||||
print 'Using user supplied C++ Compiler: ', env['CXX']
|
|
||||||
|
|
||||||
if GetOption('allflags') is not None:
|
|
||||||
env.Append(CXXFLAGS = ["-Wextra", "-Wall", "-Wnon-virtual-dtor", "-Wundef", "-Wno-long-long", "-Woverloaded-virtual", "-Wfloat-equal", "-Wredundant-decls"])
|
|
||||||
|
|
||||||
if "clang" in env["CXX"]:
|
|
||||||
print "Warning building with clang removes OpenMP parallelization"
|
|
||||||
if GetOption('allflags') is not None:
|
|
||||||
env.Append(CXXFLAGS = ["-W#warnings", "-Wc++0x-compat", "-Waddress-of-temporary", "-Wambiguous-member-template", "-Warray-bounds", "-Watomic-properties", "-Wbind-to-temporary-copy", "-Wbuiltin-macro-redefined", "-Wc++-compat", "-Wc++0x-extensions", "-Wcomments", "-Wconditional-uninitialized", "-Wconstant-logical-operand", "-Wdeclaration-after-statement", "-Wdeprecated", "-Wdeprecated-implementations", "-Wdeprecated-writable-strings", "-Wduplicate-method-arg", "-Wempty-body", "-Wendif-labels", "-Wenum-compare", "-Wformat=2", "-Wfour-char-constants", "-Wgnu", "-Wincomplete-implementation", "-Winvalid-noreturn", "-Winvalid-offsetof", "-Winvalid-token-paste", "-Wlocal-type-template-args", "-Wmethod-signatures", "-Wmicrosoft", "-Wmissing-declarations", "-Wnon-pod-varargs", "-Wnonfragile-abi2", "-Wnull-dereference", "-Wout-of-line-declaration", "-Woverlength-strings", "-Wpacked", "-Wpointer-arith", "-Wpointer-sign", "-Wprotocol", "-Wreadonly-setter-attrs", "-Wselector", "-Wshift-overflow", "-Wshift-sign-overflow", "-Wstrict-selector-match", "-Wsuper-class-method-mismatch", "-Wtautological-compare", "-Wtypedef-redefinition", "-Wundeclared-selector", "-Wunnamed-type-template-args", "-Wunused-exception-parameter", "-Wunused-member-function", "-Wused-but-marked-unused", "-Wvariadic-macros"])
|
|
||||||
else:
|
|
||||||
env.Append(CCFLAGS = ['-minline-all-stringops', '-fopenmp'])
|
|
||||||
env.Append(LINKFLAGS = '-fopenmp')
|
|
||||||
|
|
||||||
if GetOption('buildconfiguration') == 'debug':
|
|
||||||
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
|
|
||||||
else:
|
|
||||||
env.Append(CCFLAGS = ['-O3', '-DNDEBUG'])
|
|
||||||
|
|
||||||
if sys.platform == 'darwin': #Mac OS X
|
|
||||||
#os x default installations
|
|
||||||
env.Append(CPPPATH = ['/usr/include/libxml2'] )
|
|
||||||
env.Append(CPPPATH = ['/usr/X11/include']) #comes with os x
|
|
||||||
# env.Append(LIBPATH = ['/usr/X11/lib']) #needed for libpng
|
|
||||||
|
|
||||||
#assume stxxl and boost are installed via homebrew. call brew binary to get folder locations
|
|
||||||
import subprocess
|
|
||||||
stxxl_prefix = subprocess.check_output(["brew", "--prefix", "libstxxl"]).strip()
|
|
||||||
env.Append(CPPPATH = [stxxl_prefix+"/include"] )
|
|
||||||
env.Append(LIBPATH = [stxxl_prefix+"/lib"] )
|
|
||||||
boost_prefix = subprocess.check_output(["brew", "--prefix", "boost"]).strip()
|
|
||||||
env.Append(CPPPATH = [boost_prefix+"/include"] )
|
|
||||||
env.Append(LIBPATH = [boost_prefix+"/lib"] )
|
|
||||||
if not conf.CheckLibWithHeader('lua', 'lua.h', 'C'):
|
|
||||||
print "lua library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
if not conf.CheckLibWithHeader('luabind', 'luabind/luabind.hpp', 'CXX'):
|
|
||||||
print "luabind library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
elif sys.platform.startswith("freebsd"):
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs protobuf')
|
|
||||||
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
|
|
||||||
env.Append(LIBPATH = ['/usr/local/lib'])
|
|
||||||
if GetOption('stxxlroot') is not None:
|
|
||||||
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
|
|
||||||
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
|
|
||||||
print 'STXXLROOT = ', GetOption('stxxlroot')
|
|
||||||
elif sys.platform == 'win32':
|
|
||||||
#SCons really wants to use Microsoft compiler
|
|
||||||
print "Compiling is not yet supported on Windows"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "Default platform"
|
|
||||||
if GetOption('stxxlroot') is not None:
|
|
||||||
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
|
|
||||||
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
|
|
||||||
print 'STXXLROOT = ', GetOption('stxxlroot')
|
|
||||||
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
|
|
||||||
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'CXX'):
|
|
||||||
print "pthread not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
if not conf.CheckLibWithHeader('luajit-5.1', 'luajit-2.0/lua.h', 'CXX'):
|
|
||||||
print "luajit library not found. Checking for interpreter"
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs lua5.1')
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs luabind')
|
|
||||||
|
|
||||||
#Check if architecture optimizations shall be turned off
|
|
||||||
if GetOption('buildconfiguration') != 'debug' and sys.platform != 'darwin' and GetOption('nomarch') is None:
|
|
||||||
env.Append(CCFLAGS = ['-march=native'])
|
|
||||||
|
|
||||||
if not conf.CheckHeader('omp.h'):
|
|
||||||
print "Compiler does not support OpenMP. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
|
|
||||||
print "bz2 library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if GetOption('withtools') is not None:
|
|
||||||
if not conf.CheckLibWithHeader('gdal', 'gdal/gdal.h', 'CXX'):
|
|
||||||
print "gdal library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('osmpbf', 'osmpbf/osmpbf.h', 'CXX'):
|
|
||||||
print "osmpbf library not found. Exiting"
|
|
||||||
print "Either install libosmpbf-dev (Ubuntu) or use https://github.com/scrosby/OSM-binary"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('protobuf', 'google/protobuf/descriptor.h', 'CXX'):
|
|
||||||
print "Google Protobuffer library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
#check for protobuf 2.3.0
|
|
||||||
if not (conf.CheckProtobuf('2.3.0')):
|
|
||||||
print 'libprotobuf version >= 2.3.0 needed'
|
|
||||||
Exit(-1);
|
|
||||||
if not (env.Detect('protoc')):
|
|
||||||
print 'protobuffer compiler not found'
|
|
||||||
Exit(-1);
|
|
||||||
if not conf.CheckLibWithHeader('stxxl', 'stxxl.h', 'CXX'):
|
|
||||||
print "stxxl library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('xml2', 'libxml/xmlreader.h', 'CXX'):
|
|
||||||
print "libxml2 library or header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('z', 'zlib.h', 'CXX'):
|
|
||||||
print "zlib library or header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
#Check BOOST installation
|
|
||||||
if not (conf.CheckBoost('1.44')):
|
|
||||||
print 'Boost version >= 1.44 needed'
|
|
||||||
Exit(-1);
|
|
||||||
if not conf.CheckLib('boost_system', language="C++"):
|
|
||||||
if not conf.CheckLib('boost_system-mt', language="C++"):
|
|
||||||
print "boost_system library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_system-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_system-mt')
|
|
||||||
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
|
|
||||||
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
|
|
||||||
print "boost thread library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_thread-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_thread-mt')
|
|
||||||
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
|
|
||||||
if not conf.CheckLibWithHeader('boost_regex-mt', 'boost/regex.hpp', 'CXX'):
|
|
||||||
print "boost/regex.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost_regex -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_regex-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_regex-mt')
|
|
||||||
if not conf.CheckLib('boost_filesystem', language="C++"):
|
|
||||||
if not conf.CheckLib('boost_filesystem-mt', language="C++"):
|
|
||||||
print "boost_filesystem library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_filesystem-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_filesystem-mt')
|
|
||||||
if not conf.CheckCXXHeader('boost/archive/iterators/base64_from_binary.hpp'):
|
|
||||||
print "boost/archive/iterators/base64_from_binary.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/archive/iterators/binary_from_base64.hpp'):
|
|
||||||
print "boost/archive/iterators/binary_from_base64.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/archive/iterators/transform_width.hpp'):
|
|
||||||
print "boost/archive/iterators/transform_width.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/bind.hpp'):
|
|
||||||
print "boost/bind.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/circular_buffer.hpp'):
|
|
||||||
print "boost/circular_buffer.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/enable_shared_from_this.hpp'):
|
|
||||||
print "boost/bind.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/foreach.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/lexical_cast.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/logic/tribool.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/math/tr1.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/noncopyable.hpp'):
|
|
||||||
print "boost/noncopyable.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/property_tree/ptree.hpp'):
|
|
||||||
print "boost/property_tree/ptree.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/property_tree/ini_parser.hpp'):
|
|
||||||
print "boost/property_tree/ini_parser.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/shared_ptr.hpp'):
|
|
||||||
print "boost/shared_ptr.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/mutex.hpp'):
|
|
||||||
print "boost/shared_ptr.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
|
|
||||||
print "boost/thread/thread.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/condition.hpp'):
|
|
||||||
print "boost/thread/condition.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
|
|
||||||
print "boost/thread/thread.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread.hpp'):
|
|
||||||
print "boost thread header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/tuple/tuple.hpp'):
|
|
||||||
print "boost thread header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
|
|
||||||
print "boost thread header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
#checks for intels thread building blocks library
|
|
||||||
#if not conf.CheckLibWithHeader('tbb', 'tbb/tbb.h', 'CXX'):
|
|
||||||
# print "Intel TBB library not found. Exiting"
|
|
||||||
# Exit(-1)
|
|
||||||
#if not conf.CheckCXXHeader('tbb/task_scheduler_init.h'):
|
|
||||||
# print "tbb/task_scheduler_init.h not found. Exiting"
|
|
||||||
# Exit(-1)
|
|
||||||
|
|
||||||
env.Program(target = 'osrm-extract', source = ["extractor.cpp", Glob('Util/*.cpp'), Glob('Extractor/*.cpp')])
|
|
||||||
env.Program(target = 'osrm-prepare', source = ["createHierarchy.cpp", Glob('Contractor/*.cpp'), Glob('Util/SRTMLookup/*.cpp'), Glob('Algorithms/*.cpp')])
|
|
||||||
env.Program(target = 'osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp', Glob('ThirdParty/*.cc'), Glob('Server/DataStructures/*.cpp')], CCFLAGS = env['CCFLAGS'] + ['-DROUTED'])
|
|
||||||
if GetOption('withtools') is not None:
|
|
||||||
env.Program(target = 'Tools/osrm-component', source = ["Tools/componentAnalysis.cpp"])
|
|
||||||
env = conf.Finish()
|
|
||||||
|
|
||||||
+1
-1
@@ -33,7 +33,7 @@ template <typename Iterator, class HandlerT>
|
|||||||
struct APIGrammar : qi::grammar<Iterator> {
|
struct APIGrammar : qi::grammar<Iterator> {
|
||||||
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) {
|
||||||
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query);
|
||||||
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | alt_route | old_API) ) ;
|
query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ;
|
||||||
|
|
||||||
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
||||||
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
||||||
|
|||||||
@@ -20,8 +20,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#ifndef BASIC_DATASTRUCTURES_H
|
#ifndef BASIC_DATASTRUCTURES_H
|
||||||
#define BASIC_DATASTRUCTURES_H
|
#define BASIC_DATASTRUCTURES_H
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
@@ -70,15 +77,13 @@ struct Reply {
|
|||||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||||
std::string content;
|
std::string content;
|
||||||
static Reply stockReply(status_type status);
|
static Reply stockReply(status_type status);
|
||||||
void setSize(unsigned size) {
|
void setSize(const unsigned size) {
|
||||||
for (std::size_t i = 0; i < headers.size(); ++i) {
|
BOOST_FOREACH ( Header& h, headers) {
|
||||||
Header& h = headers[i];
|
if("Content-Length" == h.name) {
|
||||||
if("Content-Length" == h.name) {
|
std::string sizeString;
|
||||||
std::stringstream sizeString;
|
intToString(size,h.value);
|
||||||
sizeString << size;
|
}
|
||||||
h.value = sizeString.str();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -138,11 +143,17 @@ Reply Reply::stockReply(Reply::status_type status) {
|
|||||||
Reply rep;
|
Reply rep;
|
||||||
rep.status = status;
|
rep.status = status;
|
||||||
rep.content = ToString(status);
|
rep.content = ToString(status);
|
||||||
rep.headers.resize(2);
|
rep.headers.resize(3);
|
||||||
rep.headers[0].name = "Content-Length";
|
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||||
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
|
rep.headers[0].value = "*";
|
||||||
rep.headers[1].name = "Content-Type";
|
rep.headers[1].name = "Content-Length";
|
||||||
rep.headers[1].value = "text/html";
|
|
||||||
|
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;
|
return rep;
|
||||||
}
|
}
|
||||||
} // namespace http
|
} // namespace http
|
||||||
|
|||||||
+5
-6
@@ -21,7 +21,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef CONNECTION_H
|
#ifndef CONNECTION_H
|
||||||
#define CONNECTION_H
|
#define CONNECTION_H
|
||||||
|
|
||||||
#include <vector>
|
#include "BasicDatastructures.h"
|
||||||
|
#include "RequestHandler.h"
|
||||||
|
#include "RequestParser.h"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
@@ -30,12 +32,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
|
||||||
#include "../DataStructures/Util.h"
|
#include <zlib.h>
|
||||||
#include "BasicDatastructures.h"
|
|
||||||
#include "RequestHandler.h"
|
|
||||||
#include "RequestParser.h"
|
|
||||||
|
|
||||||
#include "zlib.h"
|
#include <vector>
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
|
|||||||
@@ -20,64 +20,107 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
|
|
||||||
#include "QueryObjectsStorage.h"
|
#include "QueryObjectsStorage.h"
|
||||||
#include "../../Util/GraphLoader.h"
|
|
||||||
|
|
||||||
QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath) {
|
QueryObjectsStorage::QueryObjectsStorage(
|
||||||
INFO("loading graph data");
|
const std::string & hsgrPath,
|
||||||
std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary);
|
const std::string & ramIndexPath,
|
||||||
if(!hsgrInStream) { ERR(hsgrPath << " not found"); }
|
const std::string & fileIndexPath,
|
||||||
|
const std::string & nodesPath,
|
||||||
|
const std::string & edgesPath,
|
||||||
|
const std::string & namesPath,
|
||||||
|
const std::string & timestampPath
|
||||||
|
) {
|
||||||
|
if( hsgrPath.empty() ) {
|
||||||
|
throw OSRMException("no hsgr file given in ini file");
|
||||||
|
}
|
||||||
|
if( ramIndexPath.empty() ) {
|
||||||
|
throw OSRMException("no ram index file given in ini file");
|
||||||
|
}
|
||||||
|
if( fileIndexPath.empty() ) {
|
||||||
|
throw OSRMException("no mem index file given in ini file");
|
||||||
|
}
|
||||||
|
if( nodesPath.empty() ) {
|
||||||
|
throw OSRMException("no nodes file given in ini file");
|
||||||
|
}
|
||||||
|
if( edgesPath.empty() ) {
|
||||||
|
throw OSRMException("no edges file given in ini file");
|
||||||
|
}
|
||||||
|
if( namesPath.empty() ) {
|
||||||
|
throw OSRMException("no names file given in ini file");
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleLogger().Write() << "loading graph data";
|
||||||
//Deserialize road network graph
|
//Deserialize road network graph
|
||||||
std::vector< QueryGraph::_StrNode> nodeList;
|
std::vector< QueryGraph::_StrNode> nodeList;
|
||||||
std::vector< QueryGraph::_StrEdge> edgeList;
|
std::vector< QueryGraph::_StrEdge> edgeList;
|
||||||
const int n = readHSGRFromStream(hsgrInStream, nodeList, edgeList, &checkSum);
|
const int n = readHSGRFromStream(
|
||||||
|
hsgrPath,
|
||||||
|
nodeList,
|
||||||
|
edgeList,
|
||||||
|
&checkSum
|
||||||
|
);
|
||||||
|
|
||||||
INFO("Data checksum is " << checkSum);
|
SimpleLogger().Write() << "Data checksum is " << checkSum;
|
||||||
graph = new QueryGraph(nodeList, edgeList);
|
graph = new QueryGraph(nodeList, edgeList);
|
||||||
assert(0 == nodeList.size());
|
assert(0 == nodeList.size());
|
||||||
assert(0 == edgeList.size());
|
assert(0 == edgeList.size());
|
||||||
|
|
||||||
if(timestampPath.length()) {
|
if(timestampPath.length()) {
|
||||||
INFO("Loading Timestamp");
|
SimpleLogger().Write() << "Loading Timestamp";
|
||||||
std::ifstream timestampInStream(timestampPath.c_str());
|
std::ifstream timestampInStream(timestampPath.c_str());
|
||||||
if(!timestampInStream) { ERR(timestampPath << " not found"); }
|
if(!timestampInStream) {
|
||||||
|
SimpleLogger().Write(logWARNING) << timestampPath << " not found";
|
||||||
|
}
|
||||||
|
|
||||||
getline(timestampInStream, timestamp);
|
getline(timestampInStream, timestamp);
|
||||||
timestampInStream.close();
|
timestampInStream.close();
|
||||||
}
|
}
|
||||||
if(!timestamp.length())
|
if(!timestamp.length()) {
|
||||||
timestamp = "n/a";
|
timestamp = "n/a";
|
||||||
if(25 < timestamp.length())
|
}
|
||||||
|
if(25 < timestamp.length()) {
|
||||||
timestamp.resize(25);
|
timestamp.resize(25);
|
||||||
|
}
|
||||||
|
|
||||||
INFO("Loading auxiliary information");
|
SimpleLogger().Write() << "Loading auxiliary information";
|
||||||
//Init nearest neighbor data structure
|
//Init nearest neighbor data structure
|
||||||
std::ifstream nodesInStream(nodesPath.c_str(), std::ios::binary);
|
nodeHelpDesk = new NodeInformationHelpDesk(
|
||||||
if(!nodesInStream) { ERR(nodesPath << " not found"); }
|
ramIndexPath,
|
||||||
std::ifstream edgesInStream(edgesPath.c_str(), std::ios::binary);
|
fileIndexPath,
|
||||||
if(!edgesInStream) { ERR(edgesPath << " not found"); }
|
nodesPath,
|
||||||
nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n, checkSum);
|
edgesPath,
|
||||||
nodeHelpDesk->initNNGrid(nodesInStream, edgesInStream);
|
n,
|
||||||
|
checkSum
|
||||||
|
);
|
||||||
|
|
||||||
//deserialize street name list
|
//deserialize street name list
|
||||||
INFO("Loading names index");
|
SimpleLogger().Write() << "Loading names index";
|
||||||
std::ifstream namesInStream(namesPath.c_str(), std::ios::binary);
|
boost::filesystem::path names_file(namesPath);
|
||||||
if(!namesInStream) { ERR(namesPath << " not found"); }
|
|
||||||
unsigned size(0);
|
if ( !boost::filesystem::exists( names_file ) ) {
|
||||||
namesInStream.read((char *)&size, sizeof(unsigned));
|
throw OSRMException("names file does not exist");
|
||||||
// names = new std::vector<std::string>();
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( names_file ) ) {
|
||||||
|
throw OSRMException("names file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
|
||||||
|
unsigned size = 0;
|
||||||
|
name_stream.read((char *)&size, sizeof(unsigned));
|
||||||
|
BOOST_ASSERT_MSG(0 != size, "name file empty");
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
for(unsigned i = 0; i < size; ++i) {
|
for( unsigned i = 0; i < size; ++i ) {
|
||||||
unsigned sizeOfString = 0;
|
unsigned size_of_string = 0;
|
||||||
namesInStream.read((char *)&sizeOfString, sizeof(unsigned));
|
name_stream.read((char *)&size_of_string, sizeof(unsigned));
|
||||||
buf[sizeOfString] = '\0'; // instead of memset
|
buf[size_of_string] = '\0'; // instead of memset
|
||||||
namesInStream.read(buf, sizeOfString);
|
name_stream.read(buf, size_of_string);
|
||||||
names.push_back(buf);
|
names.push_back(buf);
|
||||||
}
|
}
|
||||||
std::vector<std::string>(names).swap(names);
|
std::vector<std::string>(names).swap(names);
|
||||||
hsgrInStream.close();
|
BOOST_ASSERT_MSG(0 != names.size(), "could not load any names");
|
||||||
namesInStream.close();
|
name_stream.close();
|
||||||
INFO("All query data structures loaded");
|
SimpleLogger().Write() << "All query data structures loaded";
|
||||||
}
|
}
|
||||||
|
|
||||||
QueryObjectsStorage::~QueryObjectsStorage() {
|
QueryObjectsStorage::~QueryObjectsStorage() {
|
||||||
|
|||||||
@@ -22,16 +22,24 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef QUERYOBJECTSSTORAGE_H_
|
#ifndef QUERYOBJECTSSTORAGE_H_
|
||||||
#define QUERYOBJECTSSTORAGE_H_
|
#define QUERYOBJECTSSTORAGE_H_
|
||||||
|
|
||||||
#include<vector>
|
#include "../../Util/GraphLoader.h"
|
||||||
#include<string>
|
#include "../../Util/OSRMException.h"
|
||||||
|
#include "../../Util/SimpleLogger.h"
|
||||||
#include "../../DataStructures/NodeInformationHelpDesk.h"
|
#include "../../DataStructures/NodeInformationHelpDesk.h"
|
||||||
#include "../../DataStructures/QueryEdge.h"
|
#include "../../DataStructures/QueryEdge.h"
|
||||||
#include "../../DataStructures/StaticGraph.h"
|
#include "../../DataStructures/StaticGraph.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
struct QueryObjectsStorage {
|
struct QueryObjectsStorage {
|
||||||
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
typedef QueryGraph::InputEdge InputEdge;
|
typedef QueryGraph::InputEdge InputEdge;
|
||||||
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
NodeInformationHelpDesk * nodeHelpDesk;
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
@@ -39,7 +47,15 @@ struct QueryObjectsStorage {
|
|||||||
std::string timestamp;
|
std::string timestamp;
|
||||||
unsigned checkSum;
|
unsigned checkSum;
|
||||||
|
|
||||||
QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath);
|
QueryObjectsStorage(
|
||||||
|
const std::string & hsgrPath,
|
||||||
|
const std::string & ramIndexPath,
|
||||||
|
const std::string & fileIndexPath,
|
||||||
|
const std::string & nodesPath,
|
||||||
|
const std::string & edgesPath,
|
||||||
|
const std::string & namesPath,
|
||||||
|
const std::string & timestampPath
|
||||||
|
);
|
||||||
|
|
||||||
~QueryObjectsStorage();
|
~QueryObjectsStorage();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,15 +21,25 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef ROUTE_PARAMETERS_H
|
#ifndef ROUTE_PARAMETERS_H
|
||||||
#define ROUTE_PARAMETERS_H
|
#define ROUTE_PARAMETERS_H
|
||||||
|
|
||||||
|
#include "../../DataStructures/Coordinate.h"
|
||||||
|
#include "../../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
#include <boost/fusion/container/vector.hpp>
|
||||||
|
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||||
|
#include <boost/fusion/include/at_c.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
|
||||||
|
|
||||||
#include "../DataStructures/Coordinate.h"
|
|
||||||
|
|
||||||
struct RouteParameters {
|
struct RouteParameters {
|
||||||
RouteParameters() : zoomLevel(18), printInstructions(false), alternateRoute(true), geometry(true), compression(true), deprecatedAPI(false), checkSum(-1) {}
|
RouteParameters() :
|
||||||
|
zoomLevel(18),
|
||||||
|
printInstructions(false),
|
||||||
|
alternateRoute(true),
|
||||||
|
geometry(true),
|
||||||
|
compression(true),
|
||||||
|
deprecatedAPI(false),
|
||||||
|
checkSum(-1) {}
|
||||||
short zoomLevel;
|
short zoomLevel;
|
||||||
bool printInstructions;
|
bool printInstructions;
|
||||||
bool alternateRoute;
|
bool alternateRoute;
|
||||||
@@ -42,12 +52,13 @@ struct RouteParameters {
|
|||||||
std::string jsonpParameter;
|
std::string jsonpParameter;
|
||||||
std::string language;
|
std::string language;
|
||||||
std::vector<std::string> hints;
|
std::vector<std::string> hints;
|
||||||
std::vector<_Coordinate> coordinates;
|
std::vector<FixedPointCoordinate> coordinates;
|
||||||
typedef HashTable<std::string, std::string>::MyIterator OptionsIterator;
|
typedef HashTable<std::string, std::string>::const_iterator OptionsIterator;
|
||||||
|
|
||||||
void setZoomLevel(const short i) {
|
void setZoomLevel(const short i) {
|
||||||
if (18 > i && 0 < i)
|
if (18 > i && 0 < i) {
|
||||||
zoomLevel = i;
|
zoomLevel = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAlternateRouteFlag(const bool b) {
|
void setAlternateRouteFlag(const bool b) {
|
||||||
@@ -95,13 +106,11 @@ struct RouteParameters {
|
|||||||
compression = b;
|
compression = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addCoordinate(boost::fusion::vector < double, double > arg_) {
|
void addCoordinate(const boost::fusion::vector < double, double > & arg_) {
|
||||||
int lat = 100000.*boost::fusion::at_c < 0 > (arg_);
|
int lat = COORDINATE_PRECISION*boost::fusion::at_c < 0 > (arg_);
|
||||||
int lon = 100000.*boost::fusion::at_c < 1 > (arg_);
|
int lon = COORDINATE_PRECISION*boost::fusion::at_c < 1 > (arg_);
|
||||||
_Coordinate myCoordinate(lat, lon);
|
coordinates.push_back(FixedPointCoordinate(lat, lon));
|
||||||
coordinates.push_back(_Coordinate(lat, lon));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /*ROUTE_PARAMETERS_H*/
|
#endif /*ROUTE_PARAMETERS_H*/
|
||||||
+55
-58
@@ -21,95 +21,92 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef REQUEST_HANDLER_H
|
#ifndef REQUEST_HANDLER_H
|
||||||
#define REQUEST_HANDLER_H
|
#define REQUEST_HANDLER_H
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cctype> // std::tolower
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
#include "APIGrammar.h"
|
#include "APIGrammar.h"
|
||||||
#include "BasicDatastructures.h"
|
#include "BasicDatastructures.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "DataStructures/RouteParameters.h"
|
||||||
#include "../Plugins/BasePlugin.h"
|
#include "../Library/OSRM.h"
|
||||||
#include "../Plugins/RouteParameters.h"
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
namespace http {
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class RequestHandler : private boost::noncopyable {
|
class RequestHandler : private boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
explicit RequestHandler() : _pluginCount(0) { }
|
typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
|
||||||
|
explicit RequestHandler() { }
|
||||||
|
|
||||||
~RequestHandler() {
|
void handle_request(const http::Request& req, http::Reply& rep){
|
||||||
|
|
||||||
for(unsigned i = 0; i < _pluginVector.size(); i++) {
|
|
||||||
BasePlugin * tempPointer = _pluginVector[i];
|
|
||||||
delete tempPointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_request(const Request& req, Reply& rep){
|
|
||||||
//parse command
|
//parse command
|
||||||
std::string request(req.uri);
|
try {
|
||||||
|
std::string request(req.uri);
|
||||||
|
|
||||||
{ //This block logs the current request to std out. should be moved to a logging component
|
|
||||||
time_t ltime;
|
time_t ltime;
|
||||||
struct tm *Tm;
|
struct tm *Tm;
|
||||||
|
|
||||||
ltime=time(NULL);
|
ltime=time(NULL);
|
||||||
Tm=localtime(<ime);
|
Tm=localtime(<ime);
|
||||||
|
|
||||||
INFO((Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " <<
|
SimpleLogger().Write() <<
|
||||||
req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri );
|
(Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" <<
|
||||||
}
|
(Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" <<
|
||||||
try {
|
1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) <<
|
||||||
|
Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) <<
|
||||||
|
Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) <<
|
||||||
|
Tm->tm_sec << " " << req.endpoint.to_string() << " " <<
|
||||||
|
req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
|
||||||
|
req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri;
|
||||||
|
|
||||||
RouteParameters routeParameters;
|
RouteParameters routeParameters;
|
||||||
APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
|
APIGrammarParser apiParser(&routeParameters);
|
||||||
|
|
||||||
std::string::iterator it = request.begin();
|
std::string::iterator it = request.begin();
|
||||||
bool result = boost::spirit::qi::parse(it, request.end(), apiParser); // returns true if successful
|
const bool result = boost::spirit::qi::parse(
|
||||||
if (!result || (it != request.end()) ) {
|
it,
|
||||||
|
request.end(),
|
||||||
|
apiParser
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( !result || (it != request.end()) ) {
|
||||||
rep = http::Reply::stockReply(http::Reply::badRequest);
|
rep = http::Reply::stockReply(http::Reply::badRequest);
|
||||||
std::stringstream content;
|
const int position = std::distance(request.begin(), it);
|
||||||
int position = std::distance(request.begin(), it);
|
std::string tmp_position_string;
|
||||||
content << "Input seems to be malformed close to position " << position << "<br>";
|
intToString(position, tmp_position_string);
|
||||||
content << "<pre>";
|
rep.content += "Input seems to be malformed close to position ";
|
||||||
content << req.uri << "<br>";
|
rep.content += "<br><pre>";
|
||||||
for(unsigned i = 0, end = std::distance(request.begin(), it); i < end; ++i)
|
rep.content += request;
|
||||||
content << " ";
|
rep.content += tmp_position_string;
|
||||||
content << "^" << "<br>";
|
rep.content += "<br>";
|
||||||
content << "</pre>";
|
const unsigned end = std::distance(request.begin(), it);
|
||||||
rep.content += content.str();
|
for(unsigned i = 0; i < end; ++i) {
|
||||||
} else {
|
rep.content += " ";
|
||||||
//Finished parsing, lets call the right plugin to handle the request
|
|
||||||
if(pluginMap.Holds(routeParameters.service)) {
|
|
||||||
rep.status = Reply::ok;
|
|
||||||
_pluginVector[pluginMap.Find(routeParameters.service)]->HandleRequest(routeParameters, rep );
|
|
||||||
} else {
|
|
||||||
rep = Reply::stockReply(Reply::badRequest);
|
|
||||||
}
|
}
|
||||||
|
rep.content += "^<br></pre>";
|
||||||
|
} else {
|
||||||
|
//parsing done, lets call the right plugin to handle the request
|
||||||
|
routing_machine->RunQuery(routeParameters, rep);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
rep = Reply::stockReply(Reply::internalServerError);
|
rep = http::Reply::stockReply(http::Reply::internalServerError);
|
||||||
std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl;
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"[server error] code: " << e.what() << ", uri: " << req.uri;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterPlugin(BasePlugin * plugin) {
|
void RegisterRoutingMachine(OSRM * osrm) {
|
||||||
std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl;
|
routing_machine = osrm;
|
||||||
pluginMap.Add(plugin->GetDescriptor(), _pluginCount);
|
|
||||||
_pluginVector.push_back(plugin);
|
|
||||||
++_pluginCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashTable<std::string, unsigned> pluginMap;
|
OSRM * routing_machine;
|
||||||
std::vector<BasePlugin *> _pluginVector;
|
|
||||||
unsigned _pluginCount;
|
|
||||||
};
|
};
|
||||||
} // namespace http
|
|
||||||
|
|
||||||
#endif // REQUEST_HANDLER_H
|
#endif // REQUEST_HANDLER_H
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef REQUEST_PARSER_H
|
#ifndef REQUEST_PARSER_H
|
||||||
#define REQUEST_PARSER_H
|
#define REQUEST_PARSER_H
|
||||||
|
|
||||||
|
#include "BasicDatastructures.h"
|
||||||
|
|
||||||
#include <boost/logic/tribool.hpp>
|
#include <boost/logic/tribool.hpp>
|
||||||
#include <boost/tuple/tuple.hpp>
|
#include <boost/tuple/tuple.hpp>
|
||||||
#include "BasicDatastructures.h"
|
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
|
|||||||
+34
-14
@@ -21,21 +21,29 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef SERVER_H
|
#ifndef SERVER_H
|
||||||
#define SERVER_H
|
#define SERVER_H
|
||||||
|
|
||||||
#include <vector>
|
#include "Connection.h"
|
||||||
|
#include "RequestHandler.h"
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include "Connection.h"
|
#include <vector>
|
||||||
#include "RequestHandler.h"
|
|
||||||
|
|
||||||
namespace http {
|
|
||||||
|
|
||||||
class Server: private boost::noncopyable {
|
class Server: private boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
explicit Server(const std::string& address, const std::string& port, unsigned thread_pool_size) : threadPoolSize(thread_pool_size), acceptor(ioService), newConnection(new Connection(ioService, requestHandler)), requestHandler(){
|
explicit Server(
|
||||||
|
const std::string& address,
|
||||||
|
const std::string& port,
|
||||||
|
unsigned thread_pool_size
|
||||||
|
) :
|
||||||
|
threadPoolSize(thread_pool_size),
|
||||||
|
acceptor(ioService),
|
||||||
|
newConnection(new http::Connection(ioService, requestHandler)),
|
||||||
|
requestHandler()
|
||||||
|
{
|
||||||
boost::asio::ip::tcp::resolver resolver(ioService);
|
boost::asio::ip::tcp::resolver resolver(ioService);
|
||||||
boost::asio::ip::tcp::resolver::query query(address, port);
|
boost::asio::ip::tcp::resolver::query query(address, port);
|
||||||
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
|
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
|
||||||
@@ -44,7 +52,14 @@ public:
|
|||||||
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||||
acceptor.bind(endpoint);
|
acceptor.bind(endpoint);
|
||||||
acceptor.listen();
|
acceptor.listen();
|
||||||
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
|
acceptor.async_accept(
|
||||||
|
newConnection->socket(),
|
||||||
|
boost::bind(
|
||||||
|
&Server::handleAccept,
|
||||||
|
this,
|
||||||
|
boost::asio::placeholders::error
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
@@ -66,23 +81,28 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef boost::shared_ptr<Connection > ConnectionPtr;
|
|
||||||
|
|
||||||
void handleAccept(const boost::system::error_code& e) {
|
void handleAccept(const boost::system::error_code& e) {
|
||||||
if (!e) {
|
if (!e) {
|
||||||
newConnection->start();
|
newConnection->start();
|
||||||
newConnection.reset(new Connection(ioService, requestHandler));
|
newConnection.reset(
|
||||||
acceptor.async_accept(newConnection->socket(), boost::bind(&Server::handleAccept, this, boost::asio::placeholders::error));
|
new http::Connection(ioService, requestHandler)
|
||||||
|
);
|
||||||
|
acceptor.async_accept(
|
||||||
|
newConnection->socket(),
|
||||||
|
boost::bind(
|
||||||
|
&Server::handleAccept,
|
||||||
|
this,
|
||||||
|
boost::asio::placeholders::error
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned threadPoolSize;
|
unsigned threadPoolSize;
|
||||||
boost::asio::io_service ioService;
|
boost::asio::io_service ioService;
|
||||||
boost::asio::ip::tcp::acceptor acceptor;
|
boost::asio::ip::tcp::acceptor acceptor;
|
||||||
ConnectionPtr newConnection;
|
boost::shared_ptr<http::Connection> newConnection;
|
||||||
RequestHandler requestHandler;
|
RequestHandler requestHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace http
|
|
||||||
|
|
||||||
#endif // SERVER_H
|
#endif // SERVER_H
|
||||||
|
|||||||
+25
-41
@@ -16,67 +16,51 @@ You should have received a copy of the GNU Affero General Public License
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
|
||||||
Created on: 26.11.2010
|
|
||||||
Author: dennis
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SERVERFACTORY_H_
|
#ifndef SERVERFACTORY_H_
|
||||||
#define SERVERFACTORY_H_
|
#define SERVERFACTORY_H_
|
||||||
|
|
||||||
#include <zlib.h>
|
|
||||||
|
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
#include "ServerConfiguration.h"
|
#include "../Util/IniFile.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
#include "../Util/InputFileUtil.h"
|
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include <zlib.h>
|
||||||
|
|
||||||
typedef http::Server Server;
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
struct ServerFactory {
|
|
||||||
static Server * CreateServer(ServerConfiguration& serverConfig) {
|
|
||||||
|
|
||||||
if(!testDataFile(serverConfig.GetParameter("nodesData"))) {
|
|
||||||
ERR("nodes file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!testDataFile(serverConfig.GetParameter("hsgrData"))) {
|
|
||||||
ERR("hsgr file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!testDataFile(serverConfig.GetParameter("namesData"))) {
|
|
||||||
ERR("names file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!testDataFile(serverConfig.GetParameter("ramIndex"))) {
|
|
||||||
ERR("ram index file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!testDataFile(serverConfig.GetParameter("fileIndex"))) {
|
|
||||||
ERR("file index file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
struct ServerFactory : boost::noncopyable {
|
||||||
|
static Server * CreateServer( IniFile & serverConfig ) {
|
||||||
int threads = omp_get_num_procs();
|
int threads = omp_get_num_procs();
|
||||||
if(serverConfig.GetParameter("IP") == "")
|
if( serverConfig.GetParameter("IP").empty() ) {
|
||||||
serverConfig.SetParameter("IP", "0.0.0.0");
|
serverConfig.SetParameter("IP", "0.0.0.0");
|
||||||
if(serverConfig.GetParameter("Port") == "")
|
}
|
||||||
|
|
||||||
|
if( serverConfig.GetParameter("Port").empty() ) {
|
||||||
serverConfig.SetParameter("Port", "5000");
|
serverConfig.SetParameter("Port", "5000");
|
||||||
|
}
|
||||||
|
|
||||||
if(stringToInt(serverConfig.GetParameter("Threads")) != 0 && stringToInt(serverConfig.GetParameter("Threads")) <= threads)
|
if(
|
||||||
|
stringToInt(serverConfig.GetParameter("Threads")) >= 1 &&
|
||||||
|
stringToInt(serverConfig.GetParameter("Threads")) <= threads
|
||||||
|
) {
|
||||||
threads = stringToInt( serverConfig.GetParameter("Threads") );
|
threads = stringToInt( serverConfig.GetParameter("Threads") );
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "[server] http 1.1 compression handled by zlib version " << zlibVersion() << std::endl;
|
SimpleLogger().Write() <<
|
||||||
Server * server = new Server(serverConfig.GetParameter("IP"), serverConfig.GetParameter("Port"), threads);
|
"http 1.1 compression handled by zlib version " << zlibVersion();
|
||||||
|
|
||||||
|
Server * server = new Server(
|
||||||
|
serverConfig.GetParameter("IP"),
|
||||||
|
serverConfig.GetParameter("Port"),
|
||||||
|
threads
|
||||||
|
);
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Server * CreateServer(const char * iniFile) {
|
static Server * CreateServer(const char * iniFile) {
|
||||||
ServerConfiguration serverConfig(iniFile);
|
IniFile serverConfig(iniFile);
|
||||||
return CreateServer(serverConfig);
|
return CreateServer(serverConfig);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+78
-58
@@ -18,23 +18,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VERBOSE(x) x
|
|
||||||
#define VERBOSE2(x)
|
|
||||||
|
|
||||||
#ifdef NDEBUG
|
|
||||||
#undef VERBOSE
|
|
||||||
#undef VERBOSE2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <istream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../Algorithms/StronglyConnectedComponents.h"
|
#include "../Algorithms/StronglyConnectedComponents.h"
|
||||||
#include "../DataStructures/BinaryHeap.h"
|
#include "../DataStructures/BinaryHeap.h"
|
||||||
@@ -42,61 +25,98 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
#include "../DataStructures/QueryEdge.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/BaseConfiguration.h"
|
|
||||||
#include "../Util/InputFileUtil.h"
|
|
||||||
#include "../Util/GraphLoader.h"
|
#include "../Util/GraphLoader.h"
|
||||||
|
#include "../Util/IniFile.h"
|
||||||
|
#include "../Util/InputFileUtil.h"
|
||||||
|
#include "../Util/OSRMException.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
using namespace std;
|
#include <boost/foreach.hpp>
|
||||||
|
#include <fstream>
|
||||||
|
#include <istream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
typedef QueryEdge::EdgeData EdgeData;
|
typedef QueryEdge::EdgeData EdgeData;
|
||||||
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
||||||
typedef BaseConfiguration ContractorConfiguration;
|
|
||||||
|
|
||||||
std::vector<NodeInfo> internalToExternalNodeMapping;
|
std::vector<NodeInfo> internal_to_external_node_map;
|
||||||
std::vector<_Restriction> inputRestrictions;
|
std::vector<TurnRestriction> restrictions_vector;
|
||||||
std::vector<NodeID> bollardNodes;
|
std::vector<NodeID> bollard_node_IDs_vector;
|
||||||
std::vector<NodeID> trafficLightNodes;
|
std::vector<NodeID> traffic_light_node_IDs_vector;
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (int argc, char * argv[]) {
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
if(argc < 3) {
|
if(argc < 3) {
|
||||||
ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
}
|
"usage:\n" << argv[0] << " <osrm> <osrm.restrictions>";
|
||||||
std::string SRTM_ROOT;
|
return -1;
|
||||||
|
|
||||||
INFO("Using restrictions from file: " << argv[2]);
|
|
||||||
std::ifstream restrictionsInstream(argv[2], ios::binary);
|
|
||||||
if(!restrictionsInstream.good()) {
|
|
||||||
ERR("Could not access <osrm-restrictions> files");
|
|
||||||
}
|
|
||||||
_Restriction restriction;
|
|
||||||
unsigned usableRestrictionsCounter(0);
|
|
||||||
restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
|
||||||
inputRestrictions.resize(usableRestrictionsCounter);
|
|
||||||
restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
|
|
||||||
restrictionsInstream.close();
|
|
||||||
|
|
||||||
std::ifstream in;
|
|
||||||
in.open (argv[1], std::ifstream::in | std::ifstream::binary);
|
|
||||||
if (!in.is_open()) {
|
|
||||||
ERR("Cannot open " << argv[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ImportEdge> edgeList;
|
SimpleLogger().Write() <<
|
||||||
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
"Using restrictions from file: " << argv[2];
|
||||||
in.close();
|
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
|
||||||
INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
|
if(!restriction_ifstream.good()) {
|
||||||
|
throw OSRMException("Could not access <osrm-restrictions> files");
|
||||||
|
}
|
||||||
|
uint32_t usable_restriction_count = 0;
|
||||||
|
restriction_ifstream.read(
|
||||||
|
(char*)&usable_restriction_count,
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
restrictions_vector.resize(usable_restriction_count);
|
||||||
|
|
||||||
|
restriction_ifstream.read(
|
||||||
|
(char *)&(restrictions_vector[0]),
|
||||||
|
usable_restriction_count*sizeof(TurnRestriction)
|
||||||
|
);
|
||||||
|
restriction_ifstream.close();
|
||||||
|
|
||||||
|
std::ifstream input_stream;
|
||||||
|
input_stream.open( argv[1], std::ifstream::in | std::ifstream::binary );
|
||||||
|
|
||||||
|
if (!input_stream.is_open()) {
|
||||||
|
throw OSRMException("Cannot open osrm file");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ImportEdge> edge_list;
|
||||||
|
NodeID node_based_node_count = readBinaryOSRMGraphFromStream(
|
||||||
|
input_stream,
|
||||||
|
edge_list,
|
||||||
|
bollard_node_IDs_vector,
|
||||||
|
traffic_light_node_IDs_vector,
|
||||||
|
&internal_to_external_node_map,
|
||||||
|
restrictions_vector
|
||||||
|
);
|
||||||
|
input_stream.close();
|
||||||
|
|
||||||
|
SimpleLogger().Write() <<
|
||||||
|
restrictions_vector.size() << " restrictions, " <<
|
||||||
|
bollard_node_IDs_vector.size() << " bollard nodes, " <<
|
||||||
|
traffic_light_node_IDs_vector.size() << " traffic lights";
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Building an edge-expanded graph from node-based input an turn restrictions
|
* Building an edge-expanded graph from node-based input an turn restrictions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
INFO("Starting SCC graph traversal");
|
SimpleLogger().Write() << "Starting SCC graph traversal";
|
||||||
TarjanSCC * tarjan = new TarjanSCC (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping);
|
TarjanSCC * tarjan = new TarjanSCC (
|
||||||
std::vector<ImportEdge>().swap(edgeList);
|
node_based_node_count,
|
||||||
|
edge_list,
|
||||||
|
bollard_node_IDs_vector,
|
||||||
|
traffic_light_node_IDs_vector,
|
||||||
|
restrictions_vector,
|
||||||
|
internal_to_external_node_map
|
||||||
|
);
|
||||||
|
std::vector<ImportEdge>().swap(edge_list);
|
||||||
|
|
||||||
tarjan->Run();
|
tarjan->Run();
|
||||||
std::vector<_Restriction>().swap(inputRestrictions);
|
|
||||||
std::vector<NodeID>().swap(bollardNodes);
|
std::vector<TurnRestriction>().swap(restrictions_vector);
|
||||||
std::vector<NodeID>().swap(trafficLightNodes);
|
std::vector<NodeID>().swap(bollard_node_IDs_vector);
|
||||||
INFO("finished component analysis");
|
std::vector<NodeID>().swap(traffic_light_node_IDs_vector);
|
||||||
|
SimpleLogger().Write() << "finished component analysis";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../Library/OSRM.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <stack>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
//Dude, real recursions on the OS stack? You must be brave...
|
||||||
|
void print_tree(boost::property_tree::ptree const& pt, const unsigned recursion_depth)
|
||||||
|
{
|
||||||
|
boost::property_tree::ptree::const_iterator end = pt.end();
|
||||||
|
for (boost::property_tree::ptree::const_iterator it = pt.begin(); it != end; ++it) {
|
||||||
|
for(unsigned i = 0; i < recursion_depth; ++i) {
|
||||||
|
std::cout << " " << std::flush;
|
||||||
|
}
|
||||||
|
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
|
||||||
|
print_tree(it->second, recursion_depth+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char * argv[]) {
|
||||||
|
LogPolicy::GetInstance().Unmute();
|
||||||
|
try {
|
||||||
|
std::cout << "\n starting up engines, compile at "
|
||||||
|
<< __DATE__ << ", " __TIME__ << std::endl;
|
||||||
|
IniFile serverConfig((argc > 1 ? argv[1] : "server.ini"));
|
||||||
|
OSRM routing_machine((argc > 1 ? argv[1] : "server.ini"));
|
||||||
|
|
||||||
|
RouteParameters route_parameters;
|
||||||
|
route_parameters.zoomLevel = 18; //no generalization
|
||||||
|
route_parameters.printInstructions = true; //turn by turn instructions
|
||||||
|
route_parameters.alternateRoute = true; //get an alternate route, too
|
||||||
|
route_parameters.geometry = true; //retrieve geometry of route
|
||||||
|
route_parameters.compression = true; //polyline encoding
|
||||||
|
route_parameters.checkSum = UINT_MAX; //see wiki
|
||||||
|
route_parameters.service = "viaroute"; //that's routing
|
||||||
|
route_parameters.outputFormat = "json";
|
||||||
|
route_parameters.jsonpParameter = ""; //set for jsonp wrapping
|
||||||
|
route_parameters.language = ""; //unused atm
|
||||||
|
//route_parameters.hints.push_back(); // see wiki, saves I/O if done properly
|
||||||
|
|
||||||
|
FixedPointCoordinate start_coordinate(52.519930*COORDINATE_PRECISION,13.438640*COORDINATE_PRECISION);
|
||||||
|
FixedPointCoordinate target_coordinate(52.513191*COORDINATE_PRECISION,13.415852*COORDINATE_PRECISION);
|
||||||
|
route_parameters.coordinates.push_back(start_coordinate);
|
||||||
|
route_parameters.coordinates.push_back(target_coordinate);
|
||||||
|
|
||||||
|
http::Reply osrm_reply;
|
||||||
|
|
||||||
|
routing_machine.RunQuery(route_parameters, osrm_reply);
|
||||||
|
|
||||||
|
std::cout << osrm_reply.content << std::endl;
|
||||||
|
|
||||||
|
//attention: super-inefficient hack below:
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << osrm_reply.content;
|
||||||
|
|
||||||
|
boost::property_tree::ptree pt;
|
||||||
|
boost::property_tree::read_json(ss, pt);
|
||||||
|
|
||||||
|
print_tree(pt, 0);
|
||||||
|
} catch (std::exception & e) {
|
||||||
|
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
open source routing machine
|
|
||||||
Copyright (C) Dennis Luxen, 2010
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BASECONFIGURATION_H_
|
|
||||||
#define BASECONFIGURATION_H_
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <exception>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
|
|
||||||
class BaseConfiguration {
|
|
||||||
public:
|
|
||||||
BaseConfiguration(const char * configFile) {
|
|
||||||
std::ifstream config( configFile );
|
|
||||||
if(!config) {
|
|
||||||
std::cerr << "[config] .ini not found" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
try {
|
|
||||||
if (config.is_open()) {
|
|
||||||
while ( config.good() ) {
|
|
||||||
getline (config,line);
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
Tokenize(line, tokens);
|
|
||||||
if(2 == tokens.size() )
|
|
||||||
parameters.Add(tokens[0], tokens[1]);
|
|
||||||
}
|
|
||||||
config.close();
|
|
||||||
}
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
ERR("[config] " << configFile << " not found -> Exception: " <<e.what());
|
|
||||||
if(config.is_open())
|
|
||||||
config.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetParameter(const char * key){
|
|
||||||
return GetParameter(std::string(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetParameter(std::string key) {
|
|
||||||
return parameters.Find(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetParameter(const char* key, const char* value) {
|
|
||||||
SetParameter(std::string(key), std::string(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetParameter(std::string key, std::string value) {
|
|
||||||
parameters.Set(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters = "=") {
|
|
||||||
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
|
||||||
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
|
|
||||||
|
|
||||||
while (std::string::npos != pos || std::string::npos != lastPos) {
|
|
||||||
std::string temp = str.substr(lastPos, pos - lastPos);
|
|
||||||
TrimStringRight(temp);
|
|
||||||
TrimStringLeft(temp);
|
|
||||||
tokens.push_back( temp );
|
|
||||||
lastPos = str.find_first_not_of(delimiters, pos);
|
|
||||||
pos = str.find_first_of(delimiters, lastPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void TrimStringRight(std::string& str) {
|
|
||||||
std::string::size_type pos = str.find_last_not_of(" ");
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
str.erase(pos+1);
|
|
||||||
else
|
|
||||||
str.erase( str.begin() , str.end() );
|
|
||||||
}
|
|
||||||
void TrimStringLeft(std::string& str) {
|
|
||||||
std::string::size_type pos = str.find_first_not_of(" ");
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
str.erase(0, pos);
|
|
||||||
else
|
|
||||||
str.erase( str.begin() , str.end() );
|
|
||||||
}
|
|
||||||
|
|
||||||
HashTable<std::string, std::string> parameters;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* BASECONFIGURATION_H_ */
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* ContainerUtils.h
|
||||||
|
*
|
||||||
|
* Created on: 02.02.2013
|
||||||
|
* Author: dennis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONTAINERUTILS_H_
|
||||||
|
#define CONTAINERUTILS_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void sort_unique_resize(std::vector<T> & vector) {
|
||||||
|
std::sort(vector.begin(), vector.end());
|
||||||
|
unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
|
||||||
|
vector.resize(number_of_unique_elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void sort_unique_resize_shrink_vector(std::vector<T> & vector) {
|
||||||
|
sort_unique_resize(vector);
|
||||||
|
std::vector<T>().swap(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void remove_consecutive_duplicates_from_vector(std::vector<T> & vector) {
|
||||||
|
unsigned number_of_unique_elements = std::unique(vector.begin(), vector.end()) - vector.begin();
|
||||||
|
vector.resize(number_of_unique_elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONTAINERUTILS_H_ */
|
||||||
+144
-64
@@ -21,6 +21,20 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef GRAPHLOADER_H
|
#ifndef GRAPHLOADER_H
|
||||||
#define GRAPHLOADER_H
|
#define GRAPHLOADER_H
|
||||||
|
|
||||||
|
#include "OSRMException.h"
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
|
#include "../DataStructures/ImportEdge.h"
|
||||||
|
#include "../DataStructures/QueryNode.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../Util/SimpleLogger.h"
|
||||||
|
#include "../Util/UUID.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -30,40 +44,51 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include "../DataStructures/ImportNode.h"
|
|
||||||
#include "../DataStructures/ImportEdge.h"
|
|
||||||
#include "../DataStructures/NodeCoords.h"
|
|
||||||
#include "../DataStructures/Restriction.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
|
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
|
||||||
|
|
||||||
template<class EdgeT>
|
template<class EdgeT>
|
||||||
struct _ExcessRemover {
|
struct _ExcessRemover {
|
||||||
inline bool operator()( EdgeT & edge ) const {
|
inline bool operator()( const EdgeT & edge ) const {
|
||||||
return edge.source() == UINT_MAX;
|
return edge.source() == UINT_MAX;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename EdgeT>
|
template<typename EdgeT>
|
||||||
NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, std::vector<NodeID> &bollardNodes, std::vector<NodeID> &trafficLightNodes, std::vector<NodeInfo> * int2ExtNodeMap, std::vector<_Restriction> & inputRestrictions) {
|
NodeID readBinaryOSRMGraphFromStream(
|
||||||
|
std::istream &in,
|
||||||
|
std::vector<EdgeT>& edgeList,
|
||||||
|
std::vector<NodeID> &bollardNodes,
|
||||||
|
std::vector<NodeID> &trafficLightNodes,
|
||||||
|
std::vector<NodeInfo> * int2ExtNodeMap,
|
||||||
|
std::vector<TurnRestriction> & inputRestrictions
|
||||||
|
) {
|
||||||
|
const UUID uuid_orig;
|
||||||
|
UUID uuid_loaded;
|
||||||
|
in.read((char *) &uuid_loaded, sizeof(UUID));
|
||||||
|
|
||||||
|
if( !uuid_loaded.TestGraphUtil(uuid_orig) ) {
|
||||||
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
".osrm was prepared with different build.\n"
|
||||||
|
"Reprocess to get rid of this warning.";
|
||||||
|
}
|
||||||
|
|
||||||
NodeID n, source, target;
|
NodeID n, source, target;
|
||||||
EdgeID m;
|
EdgeID m;
|
||||||
short dir;// direction (0 = open, 1 = forward, 2+ = open)
|
short dir;// direction (0 = open, 1 = forward, 2+ = open)
|
||||||
ExternalNodeMap ext2IntNodeMap;
|
ExternalNodeMap ext2IntNodeMap;
|
||||||
in.read((char*)&n, sizeof(NodeID));
|
in.read((char*)&n, sizeof(NodeID));
|
||||||
DEBUG("Importing n = " << n << " nodes ");
|
SimpleLogger().Write() << "Importing n = " << n << " nodes ";
|
||||||
_Node node;
|
_Node node;
|
||||||
for (NodeID i=0; i<n; ++i) {
|
for (NodeID i=0; i<n; ++i) {
|
||||||
in.read((char*)&node, sizeof(_Node));
|
in.read((char*)&node, sizeof(_Node));
|
||||||
int2ExtNodeMap->push_back(NodeInfo(node.lat, node.lon, node.id));
|
int2ExtNodeMap->push_back(NodeInfo(node.lat, node.lon, node.id));
|
||||||
ext2IntNodeMap.insert(std::make_pair(node.id, i));
|
ext2IntNodeMap.insert(std::make_pair(node.id, i));
|
||||||
if(node.bollard)
|
if(node.bollard) {
|
||||||
bollardNodes.push_back(i);
|
bollardNodes.push_back(i);
|
||||||
if(node.trafficLight)
|
}
|
||||||
|
if(node.trafficLight) {
|
||||||
trafficLightNodes.push_back(i);
|
trafficLightNodes.push_back(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//tighten vector sizes
|
//tighten vector sizes
|
||||||
@@ -71,11 +96,11 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
std::vector<NodeID>(trafficLightNodes).swap(trafficLightNodes);
|
std::vector<NodeID>(trafficLightNodes).swap(trafficLightNodes);
|
||||||
|
|
||||||
in.read((char*)&m, sizeof(unsigned));
|
in.read((char*)&m, sizeof(unsigned));
|
||||||
DEBUG(" and " << m << " edges ");
|
SimpleLogger().Write() << " and " << m << " edges ";
|
||||||
for(unsigned i = 0; i < inputRestrictions.size(); ++i) {
|
for(unsigned i = 0; i < inputRestrictions.size(); ++i) {
|
||||||
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(inputRestrictions[i].fromNode);
|
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(inputRestrictions[i].fromNode);
|
||||||
if( intNodeID == ext2IntNodeMap.end()) {
|
if( intNodeID == ext2IntNodeMap.end()) {
|
||||||
DEBUG("Unmapped from Node of restriction");
|
SimpleLogger().Write(logDEBUG) << "Unmapped from Node of restriction";
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -83,14 +108,14 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
|
|
||||||
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].viaNode);
|
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].viaNode);
|
||||||
if( intNodeID == ext2IntNodeMap.end()) {
|
if( intNodeID == ext2IntNodeMap.end()) {
|
||||||
DEBUG("Unmapped via node of restriction");
|
SimpleLogger().Write(logDEBUG) << "Unmapped via node of restriction";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
inputRestrictions[i].viaNode = intNodeID->second;
|
inputRestrictions[i].viaNode = intNodeID->second;
|
||||||
|
|
||||||
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].toNode);
|
intNodeID = ext2IntNodeMap.find(inputRestrictions[i].toNode);
|
||||||
if( intNodeID == ext2IntNodeMap.end()) {
|
if( intNodeID == ext2IntNodeMap.end()) {
|
||||||
DEBUG("Unmapped to node of restriction");
|
SimpleLogger().Write(logDEBUG) << "Unmapped to node of restriction";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
inputRestrictions[i].toNode = intNodeID->second;
|
inputRestrictions[i].toNode = intNodeID->second;
|
||||||
@@ -101,7 +126,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
short type;
|
short type;
|
||||||
NodeID nameID;
|
NodeID nameID;
|
||||||
int length;
|
int length;
|
||||||
bool isRoundabout, ignoreInGrid, isAccessRestricted;
|
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));
|
in.read((char*)&source, sizeof(unsigned));
|
||||||
@@ -114,10 +139,11 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
in.read((char*)&isRoundabout, sizeof(bool));
|
in.read((char*)&isRoundabout, sizeof(bool));
|
||||||
in.read((char*)&ignoreInGrid, sizeof(bool));
|
in.read((char*)&ignoreInGrid, sizeof(bool));
|
||||||
in.read((char*)&isAccessRestricted, sizeof(bool));
|
in.read((char*)&isAccessRestricted, sizeof(bool));
|
||||||
|
in.read((char*)&isContraFlow, sizeof(bool));
|
||||||
|
|
||||||
GUARANTEE(length > 0, "loaded null length edge" );
|
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
|
||||||
GUARANTEE(weight > 0, "loaded null weight");
|
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||||
GUARANTEE(0<=dir && dir<=2, "loaded bogus direction");
|
BOOST_ASSERT_MSG(0<=dir && dir<=2, "loaded bogus direction");
|
||||||
|
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
bool backward = true;
|
bool backward = true;
|
||||||
@@ -130,7 +156,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
|
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
|
||||||
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
|
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
WARN(" unresolved source NodeID: " << source );
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
" unresolved source NodeID: " << source;
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -138,19 +165,22 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
intNodeID = ext2IntNodeMap.find(target);
|
intNodeID = ext2IntNodeMap.find(target);
|
||||||
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
|
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
WARN("unresolved target NodeID : " << target );
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"unresolved target NodeID : " << target;
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
target = intNodeID->second;
|
target = intNodeID->second;
|
||||||
GUARANTEE(source != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
|
BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX,
|
||||||
|
"nonexisting source or target"
|
||||||
|
);
|
||||||
|
|
||||||
if(source > target) {
|
if(source > target) {
|
||||||
std::swap(source, target);
|
std::swap(source, target);
|
||||||
std::swap(forward, backward);
|
std::swap(forward, backward);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted );
|
EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow );
|
||||||
edgeList.push_back(inputEdge);
|
edgeList.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
std::sort(edgeList.begin(), edgeList.end());
|
std::sort(edgeList.begin(), edgeList.end());
|
||||||
@@ -169,14 +199,14 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
edgeList[i]._source = UINT_MAX;
|
edgeList[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();
|
edgeList[i-1].forward = !edgeList[i].isForward();
|
||||||
edgeList[i-1].backward = ~edgeList[i].isBackward();
|
edgeList[i-1].backward = !edgeList[i].isBackward();
|
||||||
}
|
}
|
||||||
} else if (edgeFlagsAreSuperSet2) {
|
} else if (edgeFlagsAreSuperSet2) {
|
||||||
if(edgeList[i-1].weight() <= edgeList[i].weight()) {
|
if(edgeList[i-1].weight() <= edgeList[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();
|
edgeList[i].forward = !edgeList[i-1].isForward();
|
||||||
edgeList[i].backward = ~edgeList[i-1].isBackward();
|
edgeList[i].backward = !edgeList[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;
|
edgeList[i-1]._source = UINT_MAX;
|
||||||
@@ -184,10 +214,10 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<ImportEdge>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
|
typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
|
||||||
ext2IntNodeMap.clear();
|
ext2IntNodeMap.clear();
|
||||||
std::vector<ImportEdge>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
|
||||||
INFO("Graph loaded ok and has " << edgeList.size() << " edges");
|
SimpleLogger().Write() << "Graph loaded ok and has " << edgeList.size() << " edges";
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
template<typename EdgeT>
|
template<typename EdgeT>
|
||||||
@@ -197,14 +227,14 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
|
int dir, xcoord, ycoord;// direction (0 = open, 1 = forward, 2+ = open)
|
||||||
ExternalNodeMap ext2IntNodeMap;
|
ExternalNodeMap ext2IntNodeMap;
|
||||||
in >> n;
|
in >> n;
|
||||||
DEBUG("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));
|
int2ExtNodeMap->push_back(NodeInfo(xcoord, ycoord, id));
|
||||||
ext2IntNodeMap.insert(std::make_pair(id, i));
|
ext2IntNodeMap.insert(std::make_pair(id, i));
|
||||||
}
|
}
|
||||||
in >> m;
|
in >> m;
|
||||||
DEBUG(" and " << m << " edges");
|
SimpleLogger().Write(logDEBUG) << " and " << m << " edges";
|
||||||
|
|
||||||
edgeList.reserve(m);
|
edgeList.reserve(m);
|
||||||
for (EdgeID i=0; i<m; ++i) {
|
for (EdgeID i=0; i<m; ++i) {
|
||||||
@@ -215,9 +245,9 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
int length;
|
int length;
|
||||||
in >> source >> target >> length >> dir >> speedType;
|
in >> source >> target >> length >> dir >> speedType;
|
||||||
|
|
||||||
if(dir == 3)
|
if(dir == 3) {
|
||||||
dir = 0;
|
dir = 0;
|
||||||
|
}
|
||||||
switch(speedType) {
|
switch(speedType) {
|
||||||
case 1:
|
case 1:
|
||||||
weight = 130;
|
weight = 130;
|
||||||
@@ -267,38 +297,50 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
weight = length*weight/3.6;
|
weight = length*weight/3.6;
|
||||||
if(speedType == 13)
|
if(speedType == 13) {
|
||||||
weight = length;
|
weight = length;
|
||||||
|
}
|
||||||
assert(length > 0);
|
assert(length > 0);
|
||||||
assert(weight > 0);
|
assert(weight > 0);
|
||||||
if(dir <0 || dir > 2)
|
if(dir <0 || dir > 2) {
|
||||||
WARN("direction bogus: " << dir);
|
SimpleLogger().Write(logWARNING) << "direction bogus: " << dir;
|
||||||
|
}
|
||||||
assert(0<=dir && dir<=2);
|
assert(0<=dir && dir<=2);
|
||||||
|
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
bool backward = true;
|
bool backward = true;
|
||||||
if (dir == 1) backward = false;
|
if (dir == 1) {
|
||||||
if (dir == 2) forward = false;
|
backward = false;
|
||||||
|
}
|
||||||
|
if (dir == 2) {
|
||||||
|
forward = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(length == 0) { ERR("loaded null length edge"); }
|
if(length == 0) {
|
||||||
|
throw OSRMException("loaded null length edge");
|
||||||
|
}
|
||||||
|
|
||||||
// translate the external NodeIDs to internal IDs
|
// translate the external NodeIDs to internal IDs
|
||||||
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
|
ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source);
|
||||||
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
|
if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) {
|
||||||
ERR("after " << edgeList.size() << " edges" << "\n->" << source << "," << target << "," << length << "," << dir << "," << weight << "\n->unresolved source NodeID: " << source);
|
throw OSRMException("unresolvable source Node ID");
|
||||||
}
|
}
|
||||||
source = intNodeID->second;
|
source = intNodeID->second;
|
||||||
intNodeID = ext2IntNodeMap.find(target);
|
intNodeID = ext2IntNodeMap.find(target);
|
||||||
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) { ERR("unresolved target NodeID : " << target); }
|
if(ext2IntNodeMap.find(target) == ext2IntNodeMap.end()) {
|
||||||
|
throw OSRMException("unresolvable target Node ID");
|
||||||
|
}
|
||||||
target = intNodeID->second;
|
target = intNodeID->second;
|
||||||
|
|
||||||
if(source == UINT_MAX || target == UINT_MAX) { ERR("nonexisting source or target" ); }
|
if(source == UINT_MAX || target == UINT_MAX) {
|
||||||
|
throw OSRMException("nonexisting source or target" );
|
||||||
|
}
|
||||||
|
|
||||||
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
|
EdgeT inputEdge(source, target, 0, weight, forward, backward, type );
|
||||||
edgeList.push_back(inputEdge);
|
edgeList.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
ext2IntNodeMap.clear();
|
ext2IntNodeMap.clear();
|
||||||
std::vector<ImportEdge>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -314,17 +356,19 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
in >> d;
|
in >> d;
|
||||||
in >> n;
|
in >> n;
|
||||||
in >> m;
|
in >> m;
|
||||||
#ifndef DEBUG
|
|
||||||
std::cout << "expecting " << n << " nodes and " << m << " edges ..." << flush;
|
SimpleLogger().Write(logDEBUG) <<
|
||||||
#endif
|
"expecting " << n << " nodes and " << m << " edges ...";
|
||||||
|
|
||||||
edgeList.reserve(m);
|
edgeList.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);
|
assert(weight > 0);
|
||||||
if(dir <0 || dir > 3)
|
if(dir <0 || dir > 3) {
|
||||||
ERR( "[error] direction bogus: " << dir );
|
throw OSRMException( "[error] direction bogus");
|
||||||
|
}
|
||||||
assert(0<=dir && dir<=3);
|
assert(0<=dir && dir<=3);
|
||||||
|
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
@@ -333,7 +377,9 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
if (dir == 2) forward = false;
|
if (dir == 2) forward = false;
|
||||||
if (dir == 3) {backward = true; forward = true;}
|
if (dir == 3) {backward = true; forward = true;}
|
||||||
|
|
||||||
if(weight == 0) { ERR("loaded null length edge"); }
|
if(weight == 0) {
|
||||||
|
throw OSRMException("loaded null length edge");
|
||||||
|
}
|
||||||
|
|
||||||
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 ));
|
||||||
@@ -355,19 +401,53 @@ NodeID readDDSGGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename NodeT, typename EdgeT>
|
template<typename NodeT, typename EdgeT>
|
||||||
unsigned readHSGRFromStream(std::istream &in, std::vector<NodeT>& nodeList, std::vector<EdgeT> & edgeList, unsigned * checkSum) {
|
unsigned readHSGRFromStream(
|
||||||
unsigned numberOfNodes = 0;
|
const std::string & hsgr_filename,
|
||||||
in.read((char*) checkSum, sizeof(unsigned));
|
std::vector<NodeT> & node_list,
|
||||||
in.read((char*) & numberOfNodes, sizeof(unsigned));
|
std::vector<EdgeT> & edge_list,
|
||||||
nodeList.resize(numberOfNodes + 1);
|
unsigned * check_sum
|
||||||
in.read((char*) &(nodeList[0]), numberOfNodes*sizeof(NodeT));
|
) {
|
||||||
|
boost::filesystem::path hsgr_file(hsgr_filename);
|
||||||
|
if ( !boost::filesystem::exists( hsgr_file ) ) {
|
||||||
|
throw OSRMException("hsgr file does not exist");
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( hsgr_file ) ) {
|
||||||
|
throw OSRMException("hsgr file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
unsigned numberOfEdges = 0;
|
boost::filesystem::ifstream hsgr_input_stream(hsgr_file, std::ios::binary);
|
||||||
in.read((char*) &numberOfEdges, sizeof(unsigned));
|
|
||||||
edgeList.resize(numberOfEdges);
|
|
||||||
in.read((char*) &(edgeList[0]), numberOfEdges*sizeof(EdgeT));
|
|
||||||
|
|
||||||
return numberOfNodes;
|
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.";
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned number_of_nodes = 0;
|
||||||
|
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");
|
||||||
|
node_list.resize(number_of_nodes + 1);
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char*) &(node_list[0]),
|
||||||
|
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);
|
||||||
|
hsgr_input_stream.read(
|
||||||
|
(char*) &(edge_list[0]),
|
||||||
|
number_of_edges*sizeof(EdgeT)
|
||||||
|
);
|
||||||
|
hsgr_input_stream.close();
|
||||||
|
return number_of_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GRAPHLOADER_H
|
#endif // GRAPHLOADER_H
|
||||||
|
|||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INI_FILE_H_
|
||||||
|
#define INI_FILE_H_
|
||||||
|
|
||||||
|
#include "OSRMException.h"
|
||||||
|
#include "../DataStructures/HashTable.h"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class IniFile {
|
||||||
|
public:
|
||||||
|
IniFile(const char * config_filename) {
|
||||||
|
boost::filesystem::path config_file(config_filename);
|
||||||
|
if ( !boost::filesystem::exists( config_file ) ) {
|
||||||
|
std::string error = std::string(config_filename) + " not found";
|
||||||
|
throw OSRMException(error);
|
||||||
|
}
|
||||||
|
if ( 0 == boost::filesystem::file_size( config_file ) ) {
|
||||||
|
std::string error = std::string(config_filename) + " is empty";
|
||||||
|
throw OSRMException(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::filesystem::ifstream config( config_file );
|
||||||
|
std::string line;
|
||||||
|
if (config.is_open()) {
|
||||||
|
while ( config.good() ) {
|
||||||
|
getline (config,line);
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
Tokenize(line, tokens);
|
||||||
|
if(2 == tokens.size() ) {
|
||||||
|
parameters.insert(std::make_pair(tokens[0], tokens[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetParameter(const std::string & key){
|
||||||
|
return parameters.Find(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Holds(const std::string & key) const {
|
||||||
|
return parameters.Holds(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetParameter(const char* key, const char* value) {
|
||||||
|
SetParameter(std::string(key), std::string(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetParameter(const std::string & key, const std::string & value) {
|
||||||
|
parameters.insert(std::make_pair(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Tokenize(
|
||||||
|
const std::string& str,
|
||||||
|
std::vector<std::string>& tokens,
|
||||||
|
const std::string& delimiters = "="
|
||||||
|
) {
|
||||||
|
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
||||||
|
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
|
||||||
|
while (std::string::npos != pos || std::string::npos != lastPos) {
|
||||||
|
std::string temp = str.substr(lastPos, pos - lastPos);
|
||||||
|
boost::trim(temp);
|
||||||
|
tokens.push_back( temp );
|
||||||
|
lastPos = str.find_first_not_of(delimiters, pos);
|
||||||
|
pos = str.find_first_of(delimiters, lastPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HashTable<std::string, std::string> parameters;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* INI_FILE_H_ */
|
||||||
@@ -21,15 +21,17 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef INPUTFILEUTIL_H_
|
#ifndef INPUTFILEUTIL_H_
|
||||||
#define INPUTFILEUTIL_H_
|
#define INPUTFILEUTIL_H_
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
// Check if file exists and if it can be opened for reading with ifstream an object
|
// Check if file exists and if it can be opened for reading with ifstream an object
|
||||||
inline bool testDataFile(const std::string & filename){
|
inline bool testDataFile(const std::string & filename){
|
||||||
boost::filesystem::path fileToTest(filename);
|
boost::filesystem::path fileToTest(filename);
|
||||||
if(!boost::filesystem::exists(fileToTest)) {
|
if(!boost::filesystem::exists(fileToTest)) {
|
||||||
WARN("Failed to open file " << filename << " for reading.");
|
SimpleLogger().Write(logWARNING) <<
|
||||||
|
"Failed to open file " << filename << " for reading.";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user