Merge branch 'develop' for release v0.3.8
This commit is contained in:
commit
966f1d654e
1
.gitignore
vendored
1
.gitignore
vendored
@ -77,6 +77,7 @@ stxxl.errlog
|
||||
/osrm-routed
|
||||
/osrm-datastore
|
||||
/osrm-prepare
|
||||
/osrm-unlock-all
|
||||
/osrm-cli
|
||||
/nohup.out
|
||||
|
||||
|
21
.travis.yml
21
.travis.yml
@ -5,21 +5,32 @@ compiler:
|
||||
# Make sure CMake is installed
|
||||
install:
|
||||
- sudo apt-get update >/dev/null
|
||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis
|
||||
- sudo apt-get -q install libprotoc-dev libprotobuf7 libprotobuf-dev libosmpbf-dev libbz2-dev libstxxl-dev libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems
|
||||
- curl -s https://gist.githubusercontent.com/DennisOSRM/803a64a9178ec375069f/raw/ | sudo bash
|
||||
before_script:
|
||||
- sudo gem install bundler
|
||||
- rvm use 1.9.3
|
||||
- gem install bundler
|
||||
- bundle install
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. $CMAKEOPTIONS
|
||||
script: make
|
||||
script:
|
||||
- make -j 2
|
||||
- cd ..
|
||||
- cucumber -p verify
|
||||
after_script:
|
||||
# - cd ..
|
||||
# - cucumber -p verify
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
cache:
|
||||
- bundler
|
||||
- apt
|
||||
env:
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release"
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug"
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" OSRM_PORT=5000 OSRM_TIMEOUT=60
|
||||
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" OSRM_PORT=5010 OSRM_TIMEOUT=60
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
|
@ -26,60 +26,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "DouglasPeucker.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../Util/MercatorUtil.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
//These thresholds are more or less heuristically chosen.
|
||||
static double DouglasPeuckerThresholds[19] = {
|
||||
32000000., //z0
|
||||
16240000., //z1
|
||||
8240000., //z2
|
||||
4240000., //z3
|
||||
2000000., //z4
|
||||
1000000., //z5
|
||||
500000., //z6
|
||||
240000., //z7
|
||||
120000., //z8
|
||||
60000., //z9
|
||||
30000., //z10
|
||||
19000., //z11
|
||||
5000., //z12
|
||||
2000., //z13
|
||||
200., //z14
|
||||
16., //z15
|
||||
6., //z16
|
||||
3., //z17
|
||||
3. //z18
|
||||
262144., //z0
|
||||
131072., //z1
|
||||
65536., //z2
|
||||
32768., //z3
|
||||
16384., //z4
|
||||
8192., //z5
|
||||
4096., //z6
|
||||
2048., //z7
|
||||
960., //z8
|
||||
480., //z9
|
||||
240., //z10
|
||||
90., //z11
|
||||
50., //z12
|
||||
25., //z13
|
||||
15., //z14
|
||||
5., //z15
|
||||
.65, //z16
|
||||
.5, //z17
|
||||
.35 //z18
|
||||
};
|
||||
|
||||
/**
|
||||
* This distance computation does integer arithmetic only and is about twice as
|
||||
* fast as the other distance function. It is an approximation only, but works
|
||||
* more or less ok.
|
||||
* Yuck! Code duplication. This function is also in EgdeBasedNode.h
|
||||
*/
|
||||
int DouglasPeucker::fastDistance(
|
||||
double DouglasPeucker::ComputeDistance(
|
||||
const FixedPointCoordinate& point,
|
||||
const FixedPointCoordinate& segA,
|
||||
const FixedPointCoordinate& segB
|
||||
) const {
|
||||
const int p2x = (segB.lon - segA.lon);
|
||||
const int p2y = (segB.lat - segA.lat);
|
||||
const int something = p2x*p2x + p2y*p2y;
|
||||
double u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something);
|
||||
const double x = lat2y(point.lat/COORDINATE_PRECISION);
|
||||
const double y = point.lon/COORDINATE_PRECISION;
|
||||
const double a = lat2y(segA.lat/COORDINATE_PRECISION);
|
||||
const double b = segA.lon/COORDINATE_PRECISION;
|
||||
const double c = lat2y(segB.lat/COORDINATE_PRECISION);
|
||||
const double d = segB.lon/COORDINATE_PRECISION;
|
||||
double p,q,nY;
|
||||
if( std::abs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
|
||||
if (u > 1) {
|
||||
u = 1;
|
||||
} else if (u < 0) {
|
||||
u = 0;
|
||||
//discretize the result to coordinate precision. it's a hack!
|
||||
if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
const int x = segA.lon + u * p2x;
|
||||
const int y = segA.lat + u * p2y;
|
||||
|
||||
const int dx = x - point.lon;
|
||||
const int dy = y - point.lat;
|
||||
|
||||
const int dist = (dx*dx + dy*dy);
|
||||
|
||||
return dist;
|
||||
double r = (p - nY*a)/c;
|
||||
if( std::isnan(r) ) {
|
||||
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
|
||||
} else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 0.;
|
||||
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
|
||||
r = 1.;
|
||||
}
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT( !std::isnan(r) );
|
||||
if( r <= 0. ){
|
||||
nearest_location.lat = segA.lat;
|
||||
nearest_location.lon = segA.lon;
|
||||
} else if( r >= 1. ){
|
||||
nearest_location.lat = segB.lat;
|
||||
nearest_location.lon = segB.lon;
|
||||
} else { // point lies in between
|
||||
nearest_location.lat = y2lat(p)*COORDINATE_PRECISION;
|
||||
nearest_location.lon = q*COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT( nearest_location.isValid() );
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
point,
|
||||
nearest_location
|
||||
);
|
||||
BOOST_ASSERT( 0. <= approximated_distance );
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
void DouglasPeucker::Run(
|
||||
@ -91,7 +123,7 @@ void DouglasPeucker::Run(
|
||||
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
|
||||
std::size_t left_border = 0;
|
||||
std::size_t right_border = 1;
|
||||
//Sweep linerarily over array and identify those ranges that need to be checked
|
||||
//Sweep over array and identify those ranges that need to be checked
|
||||
do {
|
||||
BOOST_ASSERT_MSG(
|
||||
input_geometry[left_border].necessary,
|
||||
@ -109,7 +141,7 @@ void DouglasPeucker::Run(
|
||||
++right_border;
|
||||
} while( right_border < input_geometry.size());
|
||||
}
|
||||
while(!recursion_stack.empty()) {
|
||||
while( !recursion_stack.empty() ) {
|
||||
//pop next element
|
||||
const PairOfPoints pair = recursion_stack.top();
|
||||
recursion_stack.pop();
|
||||
@ -129,17 +161,17 @@ void DouglasPeucker::Run(
|
||||
pair.first < pair.second,
|
||||
"left border on the wrong side"
|
||||
);
|
||||
int max_distance = INT_MIN;
|
||||
double max_distance = std::numeric_limits<double>::min();
|
||||
|
||||
std::size_t farthest_element_index = pair.second;
|
||||
//find index idx of element with max_distance
|
||||
for(std::size_t i = pair.first+1; i < pair.second; ++i){
|
||||
const int temp_dist = fastDistance(
|
||||
const int temp_dist = ComputeDistance(
|
||||
input_geometry[i].location,
|
||||
input_geometry[pair.first].location,
|
||||
input_geometry[pair.second].location
|
||||
);
|
||||
const double distance = std::fabs(temp_dist);
|
||||
const double distance = std::abs(temp_dist);
|
||||
if(
|
||||
distance > DouglasPeuckerThresholds[zoom_level] &&
|
||||
distance > max_distance
|
@ -28,10 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DOUGLASPEUCKER_H_
|
||||
#define DOUGLASPEUCKER_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@ -39,30 +41,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
/*This class object computes the bitvector of indicating generalized input points
|
||||
* according to the (Ramer-)Douglas-Peucker algorithm.
|
||||
/* This class object computes the bitvector of indicating generalized input
|
||||
* points according to the (Ramer-)Douglas-Peucker algorithm.
|
||||
*
|
||||
* Input is vector of pairs. Each pair consists of the point information and a bit
|
||||
* indicating if the points is present in the generalization.
|
||||
* Input is vector of pairs. Each pair consists of the point information and a
|
||||
* bit indicating if the points is present in the generalization.
|
||||
* Note: points may also be pre-selected*/
|
||||
|
||||
struct SegmentInformation;
|
||||
|
||||
class DouglasPeucker {
|
||||
private:
|
||||
typedef std::pair<std::size_t, std::size_t> PairOfPoints;
|
||||
//Stack to simulate the recursion
|
||||
std::stack<PairOfPoints > recursion_stack;
|
||||
std::stack<PairOfPoints> recursion_stack;
|
||||
|
||||
/**
|
||||
* This distance computation does integer arithmetic only and is about twice as fast as
|
||||
* the other distance function. It is an approximation only, but works more or less ok.
|
||||
*/
|
||||
int fastDistance(
|
||||
double ComputeDistance(
|
||||
const FixedPointCoordinate& point,
|
||||
const FixedPointCoordinate& segA,
|
||||
const FixedPointCoordinate& segB
|
||||
) const;
|
||||
public:
|
||||
void Run(std::vector<SegmentInformation> & input_geometry, const unsigned zoom_level);
|
||||
void Run(
|
||||
std::vector<SegmentInformation> & input_geometry,
|
||||
const unsigned zoom_level
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
@ -25,32 +25,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ITERATORBASEDCRC32_H_
|
||||
#define ITERATORBASEDCRC32_H_
|
||||
#ifndef ITERATOR_BASED_CRC32_H
|
||||
#define ITERATOR_BASED_CRC32_H
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
#include <iostream>
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#include <cpuid.h>
|
||||
#else
|
||||
#include <boost/crc.hpp> // for boost::crc_32_type
|
||||
|
||||
inline void __get_cpuid(
|
||||
int param,
|
||||
unsigned *eax,
|
||||
unsigned *ebx,
|
||||
unsigned *ecx,
|
||||
unsigned *edx
|
||||
) { *ecx = 0; }
|
||||
#endif
|
||||
|
||||
template<class ContainerT>
|
||||
class IteratorbasedCRC32 {
|
||||
private:
|
||||
typedef typename ContainerT::iterator ContainerT_iterator;
|
||||
typedef typename ContainerT::iterator IteratorType;
|
||||
unsigned crc;
|
||||
|
||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
||||
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
||||
bool use_SSE42_CRC_function;
|
||||
|
||||
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){
|
||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor;
|
||||
CRC32_Processor.process_bytes( str, len);
|
||||
return CRC32_Processor.checksum();
|
||||
#if !defined(__x86_64__)
|
||||
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
|
||||
#endif
|
||||
unsigned SoftwareBasedCRC32( char *str, unsigned len )
|
||||
{
|
||||
#if !defined(__x86_64__)
|
||||
CRC32_processor.process_bytes( str, len);
|
||||
return CRC32_processor.checksum();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
unsigned SSEBasedCRC32( char *str, unsigned len, unsigned crc){
|
||||
unsigned q=len/sizeof(unsigned),
|
||||
r=len%sizeof(unsigned),
|
||||
*p=(unsigned*)str/*, crc*/;
|
||||
|
||||
// adapted from http://byteworm.com/2010/10/13/crc32/
|
||||
unsigned SSE42BasedCRC32( char *str, unsigned len )
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
unsigned q = len/sizeof(unsigned);
|
||||
unsigned r = len%sizeof(unsigned);
|
||||
unsigned *p = (unsigned*)str;
|
||||
|
||||
//crc=0;
|
||||
while (q--) {
|
||||
@ -71,47 +94,55 @@ private:
|
||||
);
|
||||
++str;
|
||||
}
|
||||
#endif
|
||||
return crc;
|
||||
}
|
||||
|
||||
unsigned cpuid(unsigned functionInput){
|
||||
unsigned eax;
|
||||
unsigned ebx;
|
||||
unsigned ecx;
|
||||
unsigned edx;
|
||||
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
|
||||
inline unsigned cpuid() const
|
||||
{
|
||||
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
|
||||
__get_cpuid( 1, &eax, &ebx, &ecx, &edx );
|
||||
return ecx;
|
||||
}
|
||||
|
||||
CRC32CFunctionPtr detectBestCRC32C(){
|
||||
static const int SSE42_BIT = 20;
|
||||
unsigned ecx = cpuid(1);
|
||||
bool hasSSE42 = ecx & (1 << SSE42_BIT);
|
||||
if (hasSSE42) {
|
||||
bool DetectNativeCRC32Support()
|
||||
{
|
||||
static const int SSE42_BIT = 0x00100000;
|
||||
const unsigned ecx = cpuid();
|
||||
const bool has_SSE42 = ecx & SSE42_BIT;
|
||||
if (has_SSE42) {
|
||||
SimpleLogger().Write() << "using hardware based CRC32 computation";
|
||||
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
|
||||
} else {
|
||||
SimpleLogger().Write() << "using software based CRC32 computation";
|
||||
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
|
||||
}
|
||||
return has_SSE42;
|
||||
}
|
||||
CRC32CFunctionPtr crcFunction;
|
||||
|
||||
public:
|
||||
IteratorbasedCRC32(): crc(0) {
|
||||
crcFunction = detectBestCRC32C();
|
||||
IteratorbasedCRC32() : crc(0)
|
||||
{
|
||||
use_SSE42_CRC_function = DetectNativeCRC32Support();
|
||||
}
|
||||
|
||||
virtual ~IteratorbasedCRC32() { }
|
||||
|
||||
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
|
||||
unsigned operator()( IteratorType iter, const IteratorType end )
|
||||
{
|
||||
unsigned crc = 0;
|
||||
while(iter != end) {
|
||||
char * data = reinterpret_cast<char*>(&(*iter) );
|
||||
crc =((*this).*(crcFunction))(data, sizeof(typename ContainerT::value_type*), crc);
|
||||
|
||||
if (use_SSE42_CRC_function)
|
||||
{
|
||||
crc = SSE42BasedCRC32( data, sizeof(typename ContainerT::value_type) );
|
||||
}
|
||||
else
|
||||
{
|
||||
crc = SoftwareBasedCRC32( data, sizeof(typename ContainerT::value_type) );
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* ITERATORBASEDCRC32_H_ */
|
||||
#endif /* ITERATOR_BASED_CRC32_H */
|
||||
|
@ -108,10 +108,10 @@ void PolylineCompressor::printUnencodedString(
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for(unsigned i = 0; i < polyline.size(); i++) {
|
||||
convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
@ -132,10 +132,10 @@ void PolylineCompressor::printUnencodedString(
|
||||
if(!polyline[i].necessary) {
|
||||
continue;
|
||||
}
|
||||
convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
|
@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_
|
||||
#define STRONGLYCONNECTEDCOMPONENTS_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../DataStructures/ImportEdge.h"
|
||||
@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
@ -385,7 +386,7 @@ public:
|
||||
}
|
||||
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||
|
||||
total_network_distance += 100*ApproximateDistance(
|
||||
total_network_distance += 100*FixedPointCoordinate::ApproximateDistance(
|
||||
m_coordinate_list[u].lat,
|
||||
m_coordinate_list[u].lon,
|
||||
m_coordinate_list[v].lat,
|
||||
|
302
CMakeLists.txt
302
CMakeLists.txt
@ -1,23 +1,25 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
project(OSRM)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(GIT_DESCRIPTION)
|
||||
|
||||
TRY_RUN(SHARED_LIBRARY_PATH_TYPE SHARED_LIBRARY_PATH_INFO_COMPILED ${PROJECT_BINARY_DIR}/CMakeTmp ${PROJECT_SOURCE_DIR}/cmake/size.cpp OUTPUT_VARIABLE IS_64_SYSTEM)
|
||||
if(IS_64_SYSTEM)
|
||||
message(STATUS "System supports 64 bits.")
|
||||
set( HAS64BITS 1 )
|
||||
else(IS_64_SYSTEM)
|
||||
MESSAGE(WARNING "Compiling on a 32 bit system is unsupported!")
|
||||
set( HAS64BITS 0 )
|
||||
endif(IS_64_SYSTEM)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
set(bitness 32)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(bitness 64)
|
||||
message(STATUS "Building on a 64 bit system")
|
||||
else()
|
||||
message(WARNING "Building on a 32 bit system is unsupported")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Include/)
|
||||
|
||||
add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
||||
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
|
||||
@ -27,32 +29,45 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
|
||||
COMMENT "Configuring UUID.cpp"
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp )
|
||||
add_custom_target(UUIDConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/UUID.cpp)
|
||||
|
||||
set(BOOST_COMPONENTS filesystem iostreams program_options regex system thread)
|
||||
set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread)
|
||||
|
||||
configure_file(Util/GitDescription.cpp.in ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp)
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in
|
||||
${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp
|
||||
)
|
||||
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||
add_executable(osrm-extract ${ExtractorSources} )
|
||||
add_executable(osrm-extract ${ExtractorSources})
|
||||
|
||||
file( GLOB PrepareGlob Contractor/*.cpp )
|
||||
set( PrepareSources prepare.cpp ${PrepareGlob} )
|
||||
add_executable( osrm-prepare ${PrepareSources} )
|
||||
file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
|
||||
set(PrepareSources prepare.cpp ${PrepareGlob})
|
||||
add_executable(osrm-prepare ${PrepareSources})
|
||||
|
||||
file(GLOB ServerGlob Server/*.cpp)
|
||||
file(GLOB DescriptorGlob Descriptors/*.cpp)
|
||||
file(GLOB DatastructureGlob DataStructures/*.cpp)
|
||||
file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp)
|
||||
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
|
||||
file(GLOB AlgorithmGlob Algorithms/*.cpp)
|
||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||
|
||||
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob} ${AlgorithmGlob} ${HttpGlob})
|
||||
add_library( OSRM SHARED ${OSRMSources} )
|
||||
add_library( UUID STATIC Util/UUID.cpp )
|
||||
add_library( GITDESCRIPTION STATIC Util/GitDescription.cpp )
|
||||
add_dependencies( UUID UUIDConfigure )
|
||||
add_dependencies( GITDESCRIPTION GIT_DESCRIPTION )
|
||||
set(
|
||||
OSRMSources
|
||||
${LibOSRMGlob}
|
||||
${DescriptorGlob}
|
||||
${DatastructureGlob}
|
||||
${CoordinateGlob}
|
||||
${AlgorithmGlob}
|
||||
${HttpGlob}
|
||||
)
|
||||
add_library(COORDLIB STATIC ${CoordinateGlob})
|
||||
add_library(OSRM ${OSRMSources} Util/GitDescription.cpp Util/UUID.cpp)
|
||||
add_library(UUID STATIC Util/UUID.cpp)
|
||||
add_library(GITDESCRIPTION STATIC Util/GitDescription.cpp)
|
||||
add_dependencies(UUID UUIDConfigure)
|
||||
add_dependencies(GITDESCRIPTION GIT_DESCRIPTION)
|
||||
|
||||
add_executable(osrm-routed routed.cpp ${ServerGlob})
|
||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||
@ -61,147 +76,194 @@ add_executable(osrm-datastore datastore.cpp)
|
||||
# Check the release mode
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
message(STATUS "Configuring OSRM in debug mode")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||
if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "adding profiling flags")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline")
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
message(STATUS "Configuring OSRM in release mode")
|
||||
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
|
||||
# set compile switches
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# not using Visual Studio C++
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC")
|
||||
endif()
|
||||
|
||||
# Configuring compilers
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# using Clang
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
|
||||
message(STATUS "OpenMP parallelization not available using clang++")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# using GCC
|
||||
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fopenmp -pedantic -fPIC")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||
# using Intel C++
|
||||
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
# using Visual Studio C++
|
||||
endif()
|
||||
|
||||
# Check if LTO is available
|
||||
set(LTO_FLAGS "")
|
||||
CHECK_CXX_COMPILER_FLAG("-flto" HAS_LTO_FLAG)
|
||||
if (HAS_LTO_FLAG)
|
||||
set(LTO_FLAGS "${LTO_FLAGS} -flto")
|
||||
endif (HAS_LTO_FLAG)
|
||||
|
||||
# disable partitioning of LTO process when possible (fixes Debian issues)
|
||||
set(LTO_PARTITION_FLAGS "")
|
||||
CHECK_CXX_COMPILER_FLAG("-flto-partition=none" HAS_LTO_PARTITION_FLAG)
|
||||
if (HAS_LTO_PARTITION_FLAG)
|
||||
set(LTO_PARTITION_FLAGS "${LTO_PARTITION_FLAGS} -flto-partition=none")
|
||||
endif (HAS_LTO_PARTITION_FLAG)
|
||||
|
||||
# Add Link-Time-Optimization flags, if supported (GCC >= 4.5) and enabled
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LTO_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LTO_FLAGS} ${LTO_PARTITION_FLAGS}")
|
||||
|
||||
# Configuring other platform dependencies
|
||||
if(APPLE)
|
||||
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||
message(STATUS "Set Architecture to x64 on OS X")
|
||||
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||
STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||
IF (DARWIN_VERSION GREATER 12)
|
||||
MESSAGE(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
ENDIF (DARWIN_VERSION GREATER 12)
|
||||
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
||||
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
||||
if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
|
||||
message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
endif()
|
||||
if(OSXLIBSTD)
|
||||
message(STATUS "linking against ${OSXLIBSTD}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=${OSXLIBSTD}")
|
||||
elseif(DARWIN_VERSION GREATER 12)
|
||||
message(STATUS "linking against libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries( osrm-datastore rt )
|
||||
target_link_libraries( OSRM rt )
|
||||
endif(UNIX AND NOT APPLE)
|
||||
target_link_libraries(osrm-datastore rt)
|
||||
target_link_libraries(OSRM rt)
|
||||
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)
|
||||
set(BOOST_MIN_VERSION "1.46.0")
|
||||
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
|
||||
if(NOT Boost_FOUND)
|
||||
message(FATAL_ERROR "Fatal error: Boost (version >= 1.46.0) required.\n")
|
||||
endif()
|
||||
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 GITDESCRIPTION )
|
||||
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
||||
target_link_libraries( osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION )
|
||||
target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
|
||||
target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
||||
target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
|
||||
find_package ( BZip2 REQUIRED )
|
||||
include_directories(${BZIP_INCLUDE_DIRS})
|
||||
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
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(Lua52)
|
||||
if(NOT LUA52_FOUND)
|
||||
find_package(Lua51 REQUIRED)
|
||||
if(NOT APPLE)
|
||||
find_package(LuaJIT 5.1)
|
||||
endif()
|
||||
else()
|
||||
if(NOT APPLE)
|
||||
find_package(LuaJIT 5.2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package( Threads REQUIRED )
|
||||
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
||||
|
||||
find_package( Lua52 )
|
||||
IF ( NOT LUA52_FOUND )
|
||||
find_package( Lua51 REQUIRED )
|
||||
IF (NOT APPLE)
|
||||
find_package( LuaJIT 5.1 )
|
||||
ENDIF ( NOT APPLE )
|
||||
ELSE( NOT LUA52_FOUND )
|
||||
IF(NOT APPLE)
|
||||
find_package( LuaJIT 5.2 )
|
||||
ENDIF(NOT APPLE)
|
||||
ENDIF( NOT LUA52_FOUND )
|
||||
|
||||
IF ( LUAJIT_FOUND )
|
||||
target_link_libraries( osrm-extract ${LUAJIT_LIBRARIES} )
|
||||
target_link_libraries( osrm-prepare ${LUAJIT_LIBRARIES} )
|
||||
ELSE ()
|
||||
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
||||
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
||||
ENDIF ()
|
||||
if( LUAJIT_FOUND )
|
||||
target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
|
||||
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(osrm-extract ${LUA_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${LUA_LIBRARY})
|
||||
endif()
|
||||
include_directories(${LUA_INCLUDE_DIR})
|
||||
|
||||
|
||||
find_package( LibXml2 REQUIRED )
|
||||
find_package(LibXml2 REQUIRED)
|
||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
|
||||
target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
|
||||
|
||||
find_package( Luabind REQUIRED )
|
||||
include_directories(${LUABIND_INCLUDE_DIR})
|
||||
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
|
||||
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
|
||||
|
||||
find_package( Protobuf REQUIRED )
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${LUABIND_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})
|
||||
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})
|
||||
target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${OSMPBF_LIBRARY})
|
||||
|
||||
find_package(Protobuf REQUIRED)
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${PROTOBUF_LIBRARY})
|
||||
target_link_libraries(osrm-prepare ${PROTOBUF_LIBRARY})
|
||||
|
||||
find_package(BZip2 REQUIRED)
|
||||
include_directories(${BZIP_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${BZIP2_LIBRARIES})
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_link_libraries(osrm-extract ${ZLIB_LIBRARY})
|
||||
target_link_libraries(osrm-routed ${ZLIB_LIBRARY})
|
||||
|
||||
if(WITH_TOOLS)
|
||||
message(STATUS "Activating OSRM internal tools")
|
||||
find_package( GDAL )
|
||||
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 GITDESCRIPTION
|
||||
)
|
||||
endif(GDAL_FOUND)
|
||||
add_executable ( osrm-cli Tools/simpleclient.cpp)
|
||||
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
|
||||
add_executable ( osrm-io-benchmark Tools/io-benchmark.cpp )
|
||||
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||
add_executable ( osrm-unlock-all Tools/unlock_all_mutexes.cpp )
|
||||
target_link_libraries( osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||
osrm-components
|
||||
${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
|
||||
endif()
|
||||
add_executable(osrm-cli Tools/simpleclient.cpp)
|
||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
|
||||
add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
|
||||
target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||
add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
|
||||
target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries( osrm-unlock-all rt )
|
||||
endif(UNIX AND NOT APPLE)
|
||||
endif(WITH_TOOLS)
|
||||
target_link_libraries(osrm-unlock-all rt)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
|
||||
|
||||
# Add RPATH info to executables so that when they are run after being installed
|
||||
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
|
||||
# more info see http://www.cmake.org/Wiki/CMake_RPATH_handling
|
||||
set_property(TARGET osrm-extract PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-prepare PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
install(FILES ${InstallGlob} DESTINATION include/osrm)
|
||||
install(TARGETS osrm-extract DESTINATION bin)
|
||||
install(TARGETS osrm-prepare DESTINATION bin)
|
||||
install(TARGETS osrm-datastore DESTINATION bin)
|
||||
install(TARGETS osrm-routed DESTINATION bin)
|
||||
install(TARGETS OSRM DESTINATION lib)
|
||||
list(GET Boost_LIBRARIES 1 BOOST_LIBRARY_FIRST)
|
||||
get_filename_component(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_FIRST}" PATH)
|
||||
set(BOOST_LIBRARY_LISTING "-L${BOOST_LIBRARY_LISTING}")
|
||||
foreach (lib ${Boost_LIBRARIES})
|
||||
get_filename_component(BOOST_LIBRARY_NAME "${lib}" NAME_WE)
|
||||
string(REPLACE "lib" "" BOOST_LIBRARY_NAME ${BOOST_LIBRARY_NAME})
|
||||
set(BOOST_LIBRARY_LISTING "${BOOST_LIBRARY_LISTING} -l${BOOST_LIBRARY_NAME}")
|
||||
endforeach ()
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/cmake/pkgconfig.in libosrm.pc @ONLY)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libosrm.pc DESTINATION lib/pkgconfig)
|
||||
|
@ -45,8 +45,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
@ -54,10 +52,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
class Contractor {
|
||||
|
||||
private:
|
||||
struct _ContractorEdgeData {
|
||||
_ContractorEdgeData() :
|
||||
struct ContractorEdgeData {
|
||||
ContractorEdgeData() :
|
||||
distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {}
|
||||
_ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
|
||||
ContractorEdgeData( unsigned _distance, unsigned _originalEdges, unsigned _id, bool _shortcut, bool _forward, bool _backward) :
|
||||
distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
|
||||
unsigned distance;
|
||||
unsigned id;
|
||||
@ -75,7 +73,7 @@ private:
|
||||
_HeapData( short h, bool t ) : hop(h), target(t) {}
|
||||
};
|
||||
|
||||
typedef DynamicGraph< _ContractorEdgeData > _DynamicGraph;
|
||||
typedef DynamicGraph< ContractorEdgeData > _DynamicGraph;
|
||||
// typedef BinaryHeap< NodeID, NodeID, int, _HeapData, ArrayStorage<NodeID, NodeID> > _Heap;
|
||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID> > _Heap;
|
||||
typedef _DynamicGraph::InputEdge _ContractorEdge;
|
||||
@ -118,6 +116,7 @@ public:
|
||||
Contractor( int nodes, ContainerT& inputEdges) {
|
||||
std::vector< _ContractorEdge > edges;
|
||||
edges.reserve(inputEdges.size()*2);
|
||||
temp_edge_counter = 0;
|
||||
|
||||
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
|
||||
typename ContainerT::deallocation_iterator dend = inputEdges.dend();
|
||||
@ -126,7 +125,7 @@ public:
|
||||
while(diter!=dend) {
|
||||
newEdge.source = diter->source();
|
||||
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());
|
||||
|
||||
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||
#ifndef NDEBUG
|
||||
@ -195,6 +194,7 @@ public:
|
||||
_graph = boost::make_shared<_DynamicGraph>( nodes, edges );
|
||||
edges.clear();
|
||||
std::vector<_ContractorEdge>().swap(edges);
|
||||
BOOST_ASSERT( 0 == edges.capacity() );
|
||||
// unsigned maxdegree = 0;
|
||||
// NodeID highestNode = 0;
|
||||
//
|
||||
@ -214,14 +214,14 @@ public:
|
||||
//Create temporary file
|
||||
|
||||
// GetTemporaryFileName(temporaryEdgeStorageFilename);
|
||||
temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot();
|
||||
edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
|
||||
std::cout << "contractor finished initalization" << std::endl;
|
||||
}
|
||||
|
||||
~Contractor() {
|
||||
//Delete temporary file
|
||||
// remove(temporaryEdgeStorageFilename.c_str());
|
||||
TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID);
|
||||
TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot);
|
||||
}
|
||||
|
||||
void Run() {
|
||||
@ -264,11 +264,11 @@ public:
|
||||
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
||||
|
||||
//Delete old heap data to free memory that we need for the coming operations
|
||||
BOOST_FOREACH(_ThreadData * data, threadData)
|
||||
BOOST_FOREACH(_ThreadData * data, threadData) {
|
||||
delete data;
|
||||
}
|
||||
threadData.clear();
|
||||
|
||||
|
||||
//Create new priority array
|
||||
std::vector<float> newNodePriority(remainingNodes.size());
|
||||
//this map gives the old IDs from the new ones, necessary to get a consistent graph at the end of contraction
|
||||
@ -285,12 +285,6 @@ public:
|
||||
remainingNodes[newNodeID].id = newNodeID;
|
||||
}
|
||||
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
||||
//Write dummy number of edges to temporary file
|
||||
// std::ofstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
||||
uint64_t initialFilePosition = tempStorage.tell(temporaryStorageSlotID);
|
||||
unsigned numberOfTemporaryEdges = 0;
|
||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||
|
||||
//walk over all nodes
|
||||
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
||||
const NodeID start = i;
|
||||
@ -299,11 +293,11 @@ public:
|
||||
const NodeID target = _graph->GetTarget(currentEdge);
|
||||
if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
|
||||
//Save edges of this node w/o renumbering.
|
||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID));
|
||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
|
||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||
++numberOfTemporaryEdges;
|
||||
}else {
|
||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
|
||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
|
||||
tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||
++temp_edge_counter;
|
||||
} else {
|
||||
//node is not yet contracted.
|
||||
//add (renumbered) outgoing edges to new DynamicGraph.
|
||||
_ContractorEdge newEdge;
|
||||
@ -323,9 +317,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
//Note the number of temporarily stored edges
|
||||
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
|
||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||
|
||||
//Delete map from old NodeIDs to new ones.
|
||||
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
||||
@ -394,10 +385,14 @@ public:
|
||||
_DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target);
|
||||
if(currentEdgeID < _graph->EndEdges(edge.source) ) {
|
||||
_DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID);
|
||||
if( currentEdgeData.shortcut
|
||||
&& edge.data.forward == currentEdgeData.forward
|
||||
&& edge.data.backward == currentEdgeData.backward ) {
|
||||
currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
|
||||
if( currentEdgeData.shortcut &&
|
||||
edge.data.forward == currentEdgeData.forward &&
|
||||
edge.data.backward == currentEdgeData.backward &&
|
||||
edge.data.distance < currentEdgeData.distance
|
||||
) {
|
||||
// found a duplicate edge with smaller weight, update it.
|
||||
currentEdgeData = edge.data;
|
||||
// currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -454,13 +449,13 @@ public:
|
||||
SimpleLogger().Write() << "Getting edges of minimized graph";
|
||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||
if(_graph->GetNumberOfNodes()) {
|
||||
Edge newEdge;
|
||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||
p.printStatus(node);
|
||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
||||
const NodeID target = _graph->GetTarget( edge );
|
||||
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
||||
Edge newEdge;
|
||||
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
|
||||
if( !oldNodeIDFromNewNodeIDMap.empty() ) {
|
||||
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
||||
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
||||
} else {
|
||||
@ -477,7 +472,10 @@ public:
|
||||
);
|
||||
newEdge.data.distance = data.distance;
|
||||
newEdge.data.shortcut = data.shortcut;
|
||||
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
|
||||
if(
|
||||
!data.originalViaNodeID &&
|
||||
!oldNodeIDFromNewNodeIDMap.empty()
|
||||
) {
|
||||
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
||||
} else {
|
||||
newEdge.data.id = data.id;
|
||||
@ -494,31 +492,29 @@ public:
|
||||
}
|
||||
_graph.reset();
|
||||
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
||||
BOOST_ASSERT( 0 == oldNodeIDFromNewNodeIDMap.capacity() );
|
||||
|
||||
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
||||
//Also get the edges from temporary storage
|
||||
unsigned numberOfTemporaryEdges = 0;
|
||||
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||
//loads edges of graph before renumbering, no need for further numbering action.
|
||||
NodeID start;
|
||||
NodeID target;
|
||||
//edges.reserve(edges.size()+numberOfTemporaryEdges);
|
||||
_DynamicGraph::EdgeData data;
|
||||
for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
|
||||
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID));
|
||||
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID));
|
||||
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||
Edge newEdge;
|
||||
newEdge.source = start;
|
||||
newEdge.target = target;
|
||||
newEdge.data.distance = data.distance;
|
||||
newEdge.data.shortcut = data.shortcut;
|
||||
newEdge.data.id = data.id;
|
||||
newEdge.data.forward = data.forward;
|
||||
newEdge.data.backward = data.backward;
|
||||
edges.push_back( newEdge );
|
||||
|
||||
Edge restored_edge;
|
||||
for(unsigned i = 0; i < temp_edge_counter; ++i) {
|
||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
|
||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
|
||||
tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
|
||||
restored_edge.source = start;
|
||||
restored_edge.target = target;
|
||||
restored_edge.data.distance = data.distance;
|
||||
restored_edge.data.shortcut = data.shortcut;
|
||||
restored_edge.data.id = data.id;
|
||||
restored_edge.data.forward = data.forward;
|
||||
restored_edge.data.backward = data.backward;
|
||||
edges.push_back( restored_edge );
|
||||
}
|
||||
tempStorage.deallocateSlot(temporaryStorageSlotID);
|
||||
tempStorage.DeallocateSlot(edge_storage_slot);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -548,7 +544,7 @@ private:
|
||||
|
||||
//iterate over all edges of node
|
||||
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 ){
|
||||
continue;
|
||||
}
|
||||
@ -594,7 +590,7 @@ private:
|
||||
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
|
||||
|
||||
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) {
|
||||
const _ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
|
||||
const ContractorEdgeData& inData = _graph->GetEdgeData( inEdge );
|
||||
const NodeID source = _graph->GetTarget( inEdge );
|
||||
if ( Simulate ) {
|
||||
assert( stats != NULL );
|
||||
@ -610,7 +606,7 @@ private:
|
||||
unsigned numTargets = 0;
|
||||
|
||||
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 ) {
|
||||
continue;
|
||||
}
|
||||
@ -629,7 +625,7 @@ private:
|
||||
_Dijkstra( maxDistance, numTargets, 2000, data, node );
|
||||
}
|
||||
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 ) {
|
||||
continue;
|
||||
}
|
||||
@ -645,7 +641,7 @@ private:
|
||||
_ContractorEdge newEdge;
|
||||
newEdge.source = source;
|
||||
newEdge.target = target;
|
||||
newEdge.data = _ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
|
||||
newEdge.data = ContractorEdgeData( pathDistance, outData.originalEdges + inData.originalEdges, node/*, 0, inData.turnInstruction*/, true, true, false);;
|
||||
insertedEdges.push_back( newEdge );
|
||||
std::swap( newEdge.source, newEdge.target );
|
||||
newEdge.data.forward = false;
|
||||
@ -738,7 +734,7 @@ private:
|
||||
if ( priority > targetPriority )
|
||||
return false;
|
||||
//tie breaking
|
||||
if ( fabs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
neighbours.push_back( target );
|
||||
@ -760,7 +756,7 @@ private:
|
||||
if ( priority > targetPriority)
|
||||
return false;
|
||||
//tie breaking
|
||||
if ( fabs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
if ( std::abs(priority - targetPriority) < std::numeric_limits<double>::epsilon() && bias(node, target) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -784,7 +780,8 @@ private:
|
||||
|
||||
boost::shared_ptr<_DynamicGraph> _graph;
|
||||
std::vector<_DynamicGraph::InputEdge> contractedEdges;
|
||||
unsigned temporaryStorageSlotID;
|
||||
unsigned edge_storage_slot;
|
||||
uint64_t temp_edge_counter;
|
||||
std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
|
||||
XORFastHash fastHash;
|
||||
};
|
||||
|
@ -25,7 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "EdgeBasedGraphFactory.h"
|
||||
#include "../Util/ComputeAngle.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
//TODO: CompressionWorker
|
||||
//TODO: EdgeBasedEdgeGenerator
|
||||
|
||||
// template<class Work>
|
||||
// inline static void TraverseGraph(NodeBasedDynamicGraph & graph, Work & work) {
|
||||
|
||||
// }
|
||||
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
int number_of_nodes,
|
||||
@ -43,7 +57,8 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
std::pair<NodeID, NodeID> restriction_source =
|
||||
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||
unsigned index;
|
||||
RestrictionMap::iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||
RestrictionMap::iterator restriction_iter;
|
||||
restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if(restriction_iter == m_restriction_map.end()) {
|
||||
index = m_restriction_bucket_list.size();
|
||||
m_restriction_bucket_list.resize(index+1);
|
||||
@ -93,7 +108,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
|
||||
continue;
|
||||
}
|
||||
edge.data.distance = (std::max)((int)import_edge.weight(), 1 );
|
||||
assert( edge.data.distance > 0 );
|
||||
BOOST_ASSERT( edge.data.distance > 0 );
|
||||
edge.data.shortcut = false;
|
||||
edge.data.roundabout = import_edge.isRoundabout();
|
||||
edge.data.ignoreInGrid = import_edge.ignoreInGrid();
|
||||
@ -131,8 +146,8 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges(
|
||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
||||
#ifndef NDEBUG
|
||||
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
|
||||
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
||||
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX);
|
||||
BOOST_ASSERT(node.lat1 != INT_MAX); BOOST_ASSERT(node.lon1 != INT_MAX);
|
||||
BOOST_ASSERT(node.lat2 != INT_MAX); BOOST_ASSERT(node.lon2 != INT_MAX);
|
||||
}
|
||||
#endif
|
||||
nodes.swap(m_edge_based_node_list);
|
||||
@ -143,7 +158,8 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
|
||||
const NodeID v
|
||||
) const {
|
||||
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||
RestrictionMap::const_iterator restriction_iter;
|
||||
restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter != m_restriction_map.end()) {
|
||||
const unsigned index = restriction_iter->second;
|
||||
BOOST_FOREACH(
|
||||
@ -165,7 +181,8 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
|
||||
) const {
|
||||
//only add an edge if turn is not a U-turn except it is the end of dead-end street.
|
||||
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v);
|
||||
RestrictionMap::const_iterator restriction_iter = m_restriction_map.find(restriction_source);
|
||||
RestrictionMap::const_iterator restriction_iter;
|
||||
restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter != m_restriction_map.end()) {
|
||||
const unsigned index = restriction_iter->second;
|
||||
BOOST_FOREACH(
|
||||
@ -199,13 +216,34 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(
|
||||
m_edge_based_node_list.push_back(currentNode);
|
||||
}
|
||||
|
||||
|
||||
void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||
std::ofstream & edge_data_file,
|
||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
||||
) const {
|
||||
edge_data_file.write(
|
||||
(char*)&(original_edge_data_vector[0]),
|
||||
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
|
||||
);
|
||||
original_edge_data_vector.clear();
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::Run(
|
||||
const char * original_edge_data_filename,
|
||||
lua_State *lua_state
|
||||
) {
|
||||
SimpleLogger().Write() << "Compressing geometry of input graph";
|
||||
//TODO: iterate over all turns
|
||||
|
||||
//TODO: compress geometries
|
||||
|
||||
//TODO: update turn restrictions if concerned by compression
|
||||
|
||||
//TODO: do some compression statistics
|
||||
|
||||
|
||||
SimpleLogger().Write() << "Identifying components of the road network";
|
||||
|
||||
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||
unsigned skipped_turns_counter = 0;
|
||||
unsigned node_based_edge_counter = 0;
|
||||
unsigned original_edges_counter = 0;
|
||||
@ -221,93 +259,21 @@ void EdgeBasedGraphFactory::Run(
|
||||
sizeof(unsigned)
|
||||
);
|
||||
|
||||
unsigned current_component = 0, current_component_size = 0;
|
||||
//Run a BFS on the undirected graph and identify small components
|
||||
std::queue<std::pair<NodeID, NodeID> > bfs_queue;
|
||||
std::vector<unsigned> component_index_list(
|
||||
m_node_based_graph->GetNumberOfNodes(),
|
||||
UINT_MAX
|
||||
);
|
||||
std::vector<unsigned> component_index_list;
|
||||
std::vector<NodeID> component_index_size;
|
||||
BFSCompentExplorer( component_index_list, component_index_size);
|
||||
|
||||
std::vector<NodeID> component_size_list;
|
||||
//put unexplorered node with parent pointer into queue
|
||||
for(
|
||||
NodeID node = 0,
|
||||
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
|
||||
component_index_list[node] = current_component;
|
||||
p.printIncrement();
|
||||
while(!bfs_queue.empty()) {
|
||||
//fetch element from BFS queue
|
||||
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||
bfs_queue.pop();
|
||||
// SimpleLogger().Write() << "sizeof queue: " << bfs_queue.size() <<
|
||||
// ", current_component_sizes: " << current_component_size <<
|
||||
//", 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
|
||||
++current_component_size;
|
||||
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||
if(!is_barrier_node) {
|
||||
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||
|
||||
//relaxieren edge outgoing edge like below where edge-expanded graph
|
||||
for(
|
||||
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(
|
||||
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;
|
||||
}
|
||||
if( u != w ) {
|
||||
//only add an edge if turn is not a U-turn except
|
||||
//when it is at the end of a dead-end street.
|
||||
if (!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
|
||||
component_index_list[w] = current_component;
|
||||
bfs_queue.push(std::make_pair(w,v));
|
||||
p.printIncrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//push size into vector
|
||||
component_size_list.push_back(current_component_size);
|
||||
//reset counters;
|
||||
current_component_size = 0;
|
||||
++current_component;
|
||||
}
|
||||
}
|
||||
SimpleLogger().Write() <<
|
||||
"identified: " << component_size_list.size() << " many components";
|
||||
"identified: " << component_index_size.size() << " many components";
|
||||
SimpleLogger().Write() <<
|
||||
"generating edge-expanded nodes";
|
||||
|
||||
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||
Percent p(m_node_based_graph->GetNumberOfNodes());
|
||||
//loop over all edges and generate new set of nodes.
|
||||
for(
|
||||
NodeIterator u = 0,
|
||||
number_of_nodes = m_node_based_graph->GetNumberOfNodes();
|
||||
u < number_of_nodes;
|
||||
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
||||
u < end;
|
||||
++u
|
||||
) {
|
||||
p.printIncrement();
|
||||
@ -326,8 +292,8 @@ void EdgeBasedGraphFactory::Run(
|
||||
//Note: edges that end on barrier nodes or on a turn restriction
|
||||
//may actually be in two distinct components. We choose the smallest
|
||||
const unsigned size_of_component = std::min(
|
||||
component_size_list[component_index_list[u]],
|
||||
component_size_list[component_index_list[v]]
|
||||
component_index_size[component_index_list[u]],
|
||||
component_index_size[component_index_list[v]]
|
||||
);
|
||||
|
||||
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
|
||||
@ -338,12 +304,11 @@ void EdgeBasedGraphFactory::Run(
|
||||
SimpleLogger().Write()
|
||||
<< "Generated " << m_edge_based_node_list.size() << " nodes in " <<
|
||||
"edge-expanded graph";
|
||||
SimpleLogger().Write() <<
|
||||
"generating edge-expanded edges";
|
||||
SimpleLogger().Write() << "generating edge-expanded edges";
|
||||
|
||||
std::vector<NodeID>().swap(component_size_list);
|
||||
std::vector<NodeID>().swap(component_index_size);
|
||||
BOOST_ASSERT_MSG(
|
||||
0 == component_size_list.capacity(),
|
||||
0 == component_index_size.capacity(),
|
||||
"component size vector not deallocated"
|
||||
);
|
||||
std::vector<NodeID>().swap(component_index_list);
|
||||
@ -359,9 +324,8 @@ void EdgeBasedGraphFactory::Run(
|
||||
//linear number of turns only.
|
||||
p.reinit(m_node_based_graph->GetNumberOfNodes());
|
||||
for(
|
||||
NodeIterator u = 0,
|
||||
last_node = m_node_based_graph->GetNumberOfNodes();
|
||||
u < last_node;
|
||||
NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
|
||||
u < end;
|
||||
++u
|
||||
) {
|
||||
for(
|
||||
@ -371,9 +335,10 @@ void EdgeBasedGraphFactory::Run(
|
||||
++e1
|
||||
) {
|
||||
++node_based_edge_counter;
|
||||
NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||
bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||
NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||
const NodeIterator v = m_node_based_graph->GetTarget(e1);
|
||||
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||
const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() );
|
||||
|
||||
for(
|
||||
EdgeIterator e2 = m_node_based_graph->BeginEdges(v),
|
||||
last_edge_v = m_node_based_graph->EndEdges(v);
|
||||
@ -390,39 +355,57 @@ void EdgeBasedGraphFactory::Run(
|
||||
continue;
|
||||
}
|
||||
|
||||
if(u == w && 1 != m_node_based_graph->GetOutDegree(v) ) {
|
||||
if( is_barrier_node) {
|
||||
if(u != w) {
|
||||
++skipped_turns_counter;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if ( (u == w) && (m_node_based_graph->GetOutDegree(v) > 1) ) {
|
||||
++skipped_turns_counter;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
CheckIfTurnIsRestricted(u, v, w) &&
|
||||
(to_node_of_only_restriction == UINT_MAX) &&
|
||||
(w != to_node_of_only_restriction)
|
||||
) {
|
||||
++skipped_turns_counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
//only add an edge if turn is not prohibited
|
||||
const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
|
||||
const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
|
||||
|
||||
BOOST_ASSERT(
|
||||
edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
|
||||
);
|
||||
BOOST_ASSERT(
|
||||
edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges()
|
||||
);
|
||||
BOOST_ASSERT(
|
||||
edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID
|
||||
);
|
||||
BOOST_ASSERT( edge_data1.forward );
|
||||
BOOST_ASSERT( edge_data2.forward );
|
||||
|
||||
// the following is the core of the loop.
|
||||
unsigned distance = edge_data1.distance;
|
||||
if(m_traffic_lights.find(v) != m_traffic_lights.end()) {
|
||||
if( m_traffic_lights.find(v) != m_traffic_lights.end() ) {
|
||||
distance += speed_profile.trafficSignalPenalty;
|
||||
}
|
||||
const unsigned penalty =
|
||||
GetTurnPenalty(u, v, w, lua_state);
|
||||
const int turn_penalty = GetTurnPenalty(u, v, w, lua_state);
|
||||
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
|
||||
if(turnInstruction == TurnInstructions.UTurn){
|
||||
distance += speed_profile.uTurnPenalty;
|
||||
}
|
||||
distance += penalty;
|
||||
distance += turn_penalty;
|
||||
|
||||
assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
|
||||
original_edge_data_vector.push_back(
|
||||
OriginalEdgeData(
|
||||
v,
|
||||
@ -433,11 +416,10 @@ void EdgeBasedGraphFactory::Run(
|
||||
++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)
|
||||
FlushVectorToStream(
|
||||
edge_data_file,
|
||||
original_edge_data_vector
|
||||
);
|
||||
original_edge_data_vector.clear();
|
||||
}
|
||||
|
||||
m_edge_based_edge_list.push_back(
|
||||
@ -450,23 +432,14 @@ void EdgeBasedGraphFactory::Run(
|
||||
false
|
||||
)
|
||||
);
|
||||
} else {
|
||||
++skipped_turns_counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.printIncrement();
|
||||
}
|
||||
edge_data_file.write(
|
||||
(char*)&(original_edge_data_vector[0]),
|
||||
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
|
||||
);
|
||||
edge_data_file.seekp(std::ios::beg);
|
||||
edge_data_file.write(
|
||||
(char*)&original_edges_counter,
|
||||
sizeof(unsigned)
|
||||
);
|
||||
FlushVectorToStream( edge_data_file, original_edge_data_vector );
|
||||
|
||||
edge_data_file.seekp( std::ios::beg );
|
||||
edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) );
|
||||
edge_data_file.close();
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
@ -518,11 +491,11 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
return TurnInstructions.UTurn;
|
||||
}
|
||||
|
||||
EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
|
||||
EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
|
||||
const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
|
||||
const EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
|
||||
|
||||
EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||
EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||
const EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
|
||||
const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
|
||||
|
||||
if(!data1.contraFlow && data2.contraFlow) {
|
||||
return TurnInstructions.EnterAgainstAllowedDirection;
|
||||
@ -569,10 +542,87 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
|
||||
m_node_info_list[v],
|
||||
m_node_info_list[w]
|
||||
);
|
||||
|
||||
return TurnInstructions.GetTurnDirectionOfInstruction(angle);
|
||||
}
|
||||
|
||||
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
||||
return m_node_based_graph->GetNumberOfEdges();
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::BFSCompentExplorer(
|
||||
std::vector<unsigned> & component_index_list,
|
||||
std::vector<unsigned> & component_index_size
|
||||
) const {
|
||||
std::queue<std::pair<NodeID, NodeID> > bfs_queue;
|
||||
Percent p( m_node_based_graph->GetNumberOfNodes() );
|
||||
unsigned current_component, current_component_size;
|
||||
current_component = current_component_size = 0;
|
||||
|
||||
BOOST_ASSERT( component_index_list.empty() );
|
||||
BOOST_ASSERT( component_index_size.empty() );
|
||||
|
||||
component_index_list.resize(
|
||||
m_node_based_graph->GetNumberOfNodes(),
|
||||
UINT_MAX
|
||||
);
|
||||
|
||||
//put unexplorered node with parent pointer into queue
|
||||
for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) {
|
||||
if(UINT_MAX == component_index_list[node]) {
|
||||
bfs_queue.push(std::make_pair(node, node));
|
||||
//mark node as read
|
||||
component_index_list[node] = current_component;
|
||||
p.printIncrement();
|
||||
while(!bfs_queue.empty()) {
|
||||
//fetch element from BFS queue
|
||||
std::pair<NodeID, NodeID> current_queue_item = bfs_queue.front();
|
||||
bfs_queue.pop();
|
||||
|
||||
const NodeID v = current_queue_item.first; //current node
|
||||
const NodeID u = current_queue_item.second; //parent
|
||||
//increment size counter of current component
|
||||
++current_component_size;
|
||||
const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end());
|
||||
if(!is_barrier_node) {
|
||||
const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
|
||||
|
||||
for(
|
||||
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(
|
||||
to_node_of_only_restriction != UINT_MAX &&
|
||||
w != to_node_of_only_restriction
|
||||
) {
|
||||
// At an only_-restriction but not at the right turn
|
||||
continue;
|
||||
}
|
||||
if( u != w ) {
|
||||
//only add an edge if turn is not a U-turn except
|
||||
//when it is at the end of a dead-end street.
|
||||
if (!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
|
||||
component_index_list[w] = current_component;
|
||||
bfs_queue.push(std::make_pair(w,v));
|
||||
p.printIncrement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//push size into vector
|
||||
component_index_size.push_back(current_component_size);
|
||||
//reset counters;
|
||||
current_component_size = 0;
|
||||
++current_component;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,17 +34,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../DataStructures/DeallocatingVector.h"
|
||||
#include "../DataStructures/DynamicGraph.h"
|
||||
#include "../DataStructures/EdgeBasedNode.h"
|
||||
#include "../Extractor/ExtractorStructs.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportEdge.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/OriginalEdgeData.h"
|
||||
#include "../DataStructures/Percent.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/QueryNode.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include "GeometryCompressor.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
@ -80,14 +82,17 @@ public:
|
||||
);
|
||||
|
||||
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
|
||||
|
||||
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
|
||||
|
||||
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
|
||||
|
||||
TurnInstruction AnalyzeTurn(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
const NodeID w
|
||||
) const;
|
||||
|
||||
int GetTurnPenalty(
|
||||
const NodeID u,
|
||||
const NodeID v,
|
||||
@ -112,15 +117,6 @@ private:
|
||||
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;
|
||||
@ -144,7 +140,6 @@ private:
|
||||
|
||||
RestrictionMap m_restriction_map;
|
||||
|
||||
|
||||
NodeID CheckForEmanatingIsOnlyTurn(
|
||||
const NodeID u,
|
||||
const NodeID v
|
||||
@ -160,7 +155,18 @@ private:
|
||||
NodeBasedDynamicGraph::EdgeIterator e1,
|
||||
NodeBasedDynamicGraph::NodeIterator u,
|
||||
NodeBasedDynamicGraph::NodeIterator v,
|
||||
bool belongsToTinyComponent);
|
||||
bool belongsToTinyComponent
|
||||
);
|
||||
|
||||
void BFSCompentExplorer(
|
||||
std::vector<unsigned> & component_index_list,
|
||||
std::vector<unsigned> & component_index_size
|
||||
) const;
|
||||
|
||||
void FlushVectorToStream(
|
||||
std::ofstream & edge_data_file,
|
||||
std::vector<OriginalEdgeData> & original_edge_data_vector
|
||||
) const;
|
||||
};
|
||||
|
||||
#endif /* EDGEBASEDGRAPHFACTORY_H_ */
|
||||
|
94
Contractor/GeometryCompressor.cpp
Normal file
94
Contractor/GeometryCompressor.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "GeometryCompressor.h"
|
||||
|
||||
int current_free_list_maximum = 0;
|
||||
int UniqueNumber () { return ++current_free_list_maximum; }
|
||||
|
||||
GeometryCompressor::GeometryCompressor() {
|
||||
m_free_list.resize(100);
|
||||
IncreaseFreeList();
|
||||
}
|
||||
|
||||
void GeometryCompressor::IncreaseFreeList() {
|
||||
m_compressed_geometries.resize(m_compressed_geometries.size() + 100);
|
||||
std::generate_n (m_free_list.rend(), 100, UniqueNumber);
|
||||
}
|
||||
|
||||
void GeometryCompressor::AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ) {
|
||||
//check if node_id already has a list
|
||||
boost::unordered_map<unsigned, unsigned>::const_iterator map_iterator;
|
||||
map_iterator = m_node_id_to_index_map.find( node_id );
|
||||
|
||||
unsigned geometry_bucket_index = std::numeric_limits<unsigned>::max();
|
||||
if( m_node_id_to_index_map.end() == map_iterator ) {
|
||||
//if not, create one
|
||||
if( m_free_list.empty() ) {
|
||||
IncreaseFreeList();
|
||||
}
|
||||
geometry_bucket_index = m_free_list.back();
|
||||
m_free_list.pop_back();
|
||||
} else {
|
||||
geometry_bucket_index = map_iterator->second;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( std::numeric_limits<unsigned>::max() != geometry_bucket_index );
|
||||
BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() );
|
||||
|
||||
//append contracted_node_id to m_compressed_geometries[node_id]
|
||||
m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id);
|
||||
|
||||
//append m_compressed_geometries[contracted_node_id] to m_compressed_geometries[node_id]
|
||||
map_iterator = m_node_id_to_index_map.find(contracted_node_id);
|
||||
if ( m_node_id_to_index_map.end() != map_iterator) {
|
||||
const unsigned bucket_index_to_remove = map_iterator->second;
|
||||
BOOST_ASSERT( bucket_index_to_remove < m_compressed_geometries.size() );
|
||||
|
||||
m_compressed_geometries[geometry_bucket_index].insert(
|
||||
m_compressed_geometries[geometry_bucket_index].end(),
|
||||
m_compressed_geometries[bucket_index_to_remove].begin(),
|
||||
m_compressed_geometries[bucket_index_to_remove].end()
|
||||
);
|
||||
//remove m_compressed_geometries[contracted_node_id], add to free list
|
||||
m_compressed_geometries[bucket_index_to_remove].clear();
|
||||
m_free_list.push_back(bucket_index_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryCompressor::PrintStatistics() const {
|
||||
unsigned compressed_node_count = 0;
|
||||
const unsigned surviving_node_count = m_compressed_geometries.size();
|
||||
|
||||
BOOST_FOREACH(const std::vector<unsigned> & current_vector, m_compressed_geometries) {
|
||||
compressed_node_count += current_vector.size();
|
||||
}
|
||||
SimpleLogger().Write() <<
|
||||
"surv: " << surviving_node_count <<
|
||||
", comp: " << compressed_node_count <<
|
||||
", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) );
|
||||
}
|
58
Contractor/GeometryCompressor.h
Normal file
58
Contractor/GeometryCompressor.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#ifndef GEOMETRY_COMPRESSOR_H
|
||||
#define GEOMETRY_COMPRESSOR_H
|
||||
|
||||
class GeometryCompressor {
|
||||
public:
|
||||
GeometryCompressor();
|
||||
void AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id );
|
||||
void PrintStatistics() const;
|
||||
|
||||
private:
|
||||
|
||||
void IncreaseFreeList();
|
||||
|
||||
std::vector<std::vector<unsigned> > m_compressed_geometries;
|
||||
std::vector<unsigned> m_free_list;
|
||||
boost::unordered_map<unsigned, unsigned> m_node_id_to_index_map;
|
||||
};
|
||||
|
||||
|
||||
#endif //GEOMETRY_COMPRESSOR_H
|
@ -28,113 +28,135 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "TemporaryStorage.h"
|
||||
|
||||
TemporaryStorage::TemporaryStorage() {
|
||||
tempDirectory = boost::filesystem::temp_directory_path();
|
||||
temp_directory = boost::filesystem::temp_directory_path();
|
||||
}
|
||||
|
||||
TemporaryStorage & TemporaryStorage::GetInstance(){
|
||||
static TemporaryStorage runningInstance;
|
||||
return runningInstance;
|
||||
static TemporaryStorage static_instance;
|
||||
return static_instance;
|
||||
}
|
||||
|
||||
TemporaryStorage::~TemporaryStorage() {
|
||||
removeAll();
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
void TemporaryStorage::removeAll() {
|
||||
void TemporaryStorage::RemoveAll() {
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) {
|
||||
deallocateSlot(slot_id);
|
||||
for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
|
||||
DeallocateSlot(slot_id);
|
||||
}
|
||||
vectorOfStreamDatas.clear();
|
||||
stream_data_list.clear();
|
||||
}
|
||||
|
||||
int TemporaryStorage::allocateSlot() {
|
||||
int TemporaryStorage::AllocateSlot() {
|
||||
boost::mutex::scoped_lock lock(mutex);
|
||||
try {
|
||||
vectorOfStreamDatas.push_back(StreamData());
|
||||
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
|
||||
stream_data_list.push_back(StreamData());
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
return vectorOfStreamDatas.size() - 1;
|
||||
CheckIfTemporaryDeviceFull();
|
||||
return stream_data_list.size() - 1;
|
||||
}
|
||||
|
||||
void TemporaryStorage::deallocateSlot(int slotID) {
|
||||
void TemporaryStorage::DeallocateSlot(const int slot_id) {
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
if(!boost::filesystem::exists(data.pathToTemporaryFile)) {
|
||||
if(!boost::filesystem::exists(data.temp_path)) {
|
||||
return;
|
||||
}
|
||||
if(data.streamToTemporaryFile->is_open()) {
|
||||
data.streamToTemporaryFile->close();
|
||||
if(data.temp_file->is_open()) {
|
||||
data.temp_file->close();
|
||||
}
|
||||
|
||||
boost::filesystem::remove(data.pathToTemporaryFile);
|
||||
boost::filesystem::remove(data.temp_path);
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
}
|
||||
|
||||
void TemporaryStorage::writeToSlot(int slotID, char * pointer, std::streamsize size) {
|
||||
void TemporaryStorage::WriteToSlot(
|
||||
const int slot_id,
|
||||
char * pointer,
|
||||
const std::size_t size
|
||||
) {
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
BOOST_ASSERT(data.write_mode);
|
||||
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
BOOST_ASSERT_MSG(
|
||||
data.writeMode,
|
||||
data.write_mode,
|
||||
"Writing after first read is not allowed"
|
||||
);
|
||||
data.streamToTemporaryFile->write(pointer, size);
|
||||
if( 1073741824 < data.buffer.size() ) {
|
||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||
// data.temp_file->write(pointer, size);
|
||||
data.buffer.clear();
|
||||
CheckIfTemporaryDeviceFull();
|
||||
}
|
||||
data.buffer.insert(data.buffer.end(), pointer, pointer+size);
|
||||
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
}
|
||||
void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
|
||||
void TemporaryStorage::ReadFromSlot(
|
||||
const int slot_id,
|
||||
char * pointer,
|
||||
const std::size_t size
|
||||
) {
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
if(data.writeMode) {
|
||||
data.writeMode = false;
|
||||
data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
|
||||
if( data.write_mode ) {
|
||||
data.write_mode = false;
|
||||
data.temp_file->write(&data.buffer[0], data.buffer.size());
|
||||
data.buffer.clear();
|
||||
data.temp_file->seekg( data.temp_file->beg );
|
||||
BOOST_ASSERT( data.temp_file->beg == data.temp_file->tellg() );
|
||||
}
|
||||
data.streamToTemporaryFile->read(pointer, size);
|
||||
BOOST_ASSERT( !data.write_mode );
|
||||
data.temp_file->read(pointer, size);
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() {
|
||||
boost::filesystem::space_info tempSpaceInfo;
|
||||
uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
|
||||
uint64_t value = -1;
|
||||
try {
|
||||
tempSpaceInfo = boost::filesystem::space(tempDirectory);
|
||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
||||
boost::filesystem::space_info s = boost::filesystem::space( p );
|
||||
value = s.free;
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
return tempSpaceInfo.available;
|
||||
return value;
|
||||
}
|
||||
|
||||
boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) {
|
||||
void TemporaryStorage::CheckIfTemporaryDeviceFull() {
|
||||
boost::filesystem::path p = boost::filesystem::temp_directory_path();
|
||||
boost::filesystem::space_info s = boost::filesystem::space( p );
|
||||
if( (1024*1024) > s.free ) {
|
||||
throw OSRMException("temporary device is full");
|
||||
}
|
||||
}
|
||||
|
||||
boost::filesystem::fstream::pos_type TemporaryStorage::Tell(const int slot_id) {
|
||||
boost::filesystem::fstream::pos_type position;
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
StreamData & data = stream_data_list[slot_id];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
position = data.streamToTemporaryFile->tellp();
|
||||
position = data.temp_file->tellp();
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
Abort(e);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) {
|
||||
removeAll();
|
||||
}
|
||||
|
||||
void TemporaryStorage::seek(int slotID, boost::filesystem::fstream::pos_type position) {
|
||||
try {
|
||||
StreamData & data = vectorOfStreamDatas[slotID];
|
||||
boost::mutex::scoped_lock lock(*data.readWriteMutex);
|
||||
data.streamToTemporaryFile->seekg(position);
|
||||
} catch(boost::filesystem::filesystem_error & e) {
|
||||
abort(e);
|
||||
}
|
||||
void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
|
||||
RemoveAll();
|
||||
throw OSRMException(e.what());
|
||||
}
|
||||
|
@ -28,46 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef TEMPORARYSTORAGE_H_
|
||||
#define TEMPORARYSTORAGE_H_
|
||||
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#include "../Util/BoostFileSystemFix.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
//This is one big workaround for latest boost renaming woes.
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
#if BOOST_FILESYSTEM_VERSION < 3
|
||||
#warning Boost Installation with Filesystem3 missing, activating workaround
|
||||
#include <cstdio>
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
inline path temp_directory_path() {
|
||||
char * buffer;
|
||||
buffer = tmpnam (NULL);
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
return path(buffer);
|
||||
}
|
||||
|
||||
inline path unique_path(const path&) {
|
||||
return temp_directory_path();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_FILESYSTEM_VERSION
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
#endif
|
||||
/**
|
||||
* This class implements a singleton file storage for temporary data.
|
||||
* temporary slots can be accessed by other objects through an int
|
||||
@ -77,49 +54,65 @@ inline path unique_path(const path&) {
|
||||
* -> Data is written in first phase and reread in second.
|
||||
*/
|
||||
|
||||
static boost::filesystem::path tempDirectory;
|
||||
static boost::filesystem::path temp_directory;
|
||||
static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
|
||||
class TemporaryStorage {
|
||||
public:
|
||||
static TemporaryStorage & GetInstance();
|
||||
virtual ~TemporaryStorage();
|
||||
|
||||
int allocateSlot();
|
||||
void deallocateSlot(int slotID);
|
||||
void writeToSlot(int slotID, char * pointer, std::streamsize size);
|
||||
void readFromSlot(int slotID, char * pointer, std::streamsize size);
|
||||
int AllocateSlot();
|
||||
void DeallocateSlot(const int slot_id);
|
||||
void WriteToSlot(const int slot_id, char * pointer, const std::size_t size);
|
||||
void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size);
|
||||
//returns the number of free bytes
|
||||
unsigned getFreeBytesOnTemporaryDevice();
|
||||
boost::filesystem::fstream::pos_type tell(int slotID);
|
||||
void seek(int slotID, boost::filesystem::fstream::pos_type);
|
||||
void removeAll();
|
||||
uint64_t GetFreeBytesOnTemporaryDevice();
|
||||
boost::filesystem::fstream::pos_type Tell(const int slot_id);
|
||||
void RemoveAll();
|
||||
private:
|
||||
TemporaryStorage();
|
||||
TemporaryStorage(TemporaryStorage const &){};
|
||||
TemporaryStorage& operator=(TemporaryStorage const &) {
|
||||
|
||||
TemporaryStorage & operator=(TemporaryStorage const &) {
|
||||
return *this;
|
||||
}
|
||||
void abort(boost::filesystem::filesystem_error& e);
|
||||
|
||||
void Abort(const boost::filesystem::filesystem_error& e);
|
||||
void CheckIfTemporaryDeviceFull();
|
||||
|
||||
struct StreamData {
|
||||
bool writeMode;
|
||||
boost::filesystem::path pathToTemporaryFile;
|
||||
boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile;
|
||||
bool write_mode;
|
||||
boost::filesystem::path temp_path;
|
||||
boost::shared_ptr<boost::filesystem::fstream> temp_file;
|
||||
boost::shared_ptr<boost::mutex> readWriteMutex;
|
||||
std::vector<char> buffer;
|
||||
|
||||
StreamData() :
|
||||
writeMode(true),
|
||||
pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))),
|
||||
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)),
|
||||
readWriteMutex(new boost::mutex)
|
||||
write_mode(true),
|
||||
temp_path(
|
||||
boost::filesystem::unique_path(
|
||||
temp_directory.append(
|
||||
TemporaryFilePattern.begin(),
|
||||
TemporaryFilePattern.end()
|
||||
)
|
||||
)
|
||||
),
|
||||
temp_file(
|
||||
new boost::filesystem::fstream(
|
||||
temp_path,
|
||||
std::ios::in|std::ios::out|std::ios::trunc|std::ios::binary
|
||||
)
|
||||
),
|
||||
readWriteMutex(boost::make_shared<boost::mutex>())
|
||||
{
|
||||
if(streamToTemporaryFile->fail()) {
|
||||
if( temp_file->fail() ) {
|
||||
throw OSRMException("temporary file could not be created");
|
||||
}
|
||||
}
|
||||
};
|
||||
//vector of file streams that is used to store temporary data
|
||||
std::vector<StreamData> vectorOfStreamDatas;
|
||||
boost::mutex mutex;
|
||||
std::vector<StreamData> stream_data_list;
|
||||
};
|
||||
|
||||
#endif /* TEMPORARYSTORAGE_H_ */
|
||||
|
@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BINARYHEAP_H_INCLUDED
|
||||
#define BINARYHEAP_H_INCLUDED
|
||||
#ifndef BINARY_HEAP_H
|
||||
#define BINARY_HEAP_H
|
||||
|
||||
//Not compatible with non contiguous node ids
|
||||
|
||||
@ -82,6 +82,9 @@ private:
|
||||
|
||||
template< typename NodeID, typename Key >
|
||||
class UnorderedMapStorage {
|
||||
typedef boost::unordered_map<NodeID, Key> UnorderedMapType;
|
||||
typedef typename UnorderedMapType::iterator UnorderedMapIterator;
|
||||
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
|
||||
public:
|
||||
|
||||
UnorderedMapStorage( size_t ) {
|
||||
@ -89,7 +92,7 @@ public:
|
||||
nodes.rehash(1000);
|
||||
}
|
||||
|
||||
Key &operator[]( const NodeID node ) {
|
||||
Key & operator[]( const NodeID node ) {
|
||||
return nodes[node];
|
||||
}
|
||||
|
||||
@ -101,13 +104,13 @@ private:
|
||||
boost::unordered_map< NodeID, Key > nodes;
|
||||
};
|
||||
|
||||
template<typename NodeID = unsigned>
|
||||
struct _SimpleHeapData {
|
||||
NodeID parent;
|
||||
_SimpleHeapData( NodeID p ) : parent(p) { }
|
||||
};
|
||||
|
||||
template < typename NodeID, typename Key, typename Weight, typename Data, typename IndexStorage = ArrayStorage<NodeID, NodeID> >
|
||||
template<
|
||||
typename NodeID,
|
||||
typename Key,
|
||||
typename Weight,
|
||||
typename Data,
|
||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>
|
||||
>
|
||||
class BinaryHeap {
|
||||
private:
|
||||
BinaryHeap( const BinaryHeap& right );
|
||||
@ -117,7 +120,9 @@ public:
|
||||
typedef Data DataType;
|
||||
|
||||
BinaryHeap( size_t maxID )
|
||||
: nodeIndex( maxID ) {
|
||||
:
|
||||
nodeIndex( maxID )
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
@ -210,11 +215,13 @@ public:
|
||||
private:
|
||||
class HeapNode {
|
||||
public:
|
||||
HeapNode() {
|
||||
}
|
||||
HeapNode( NodeID n, Key k, Weight w, Data d )
|
||||
: node( n ), key( k ), weight( w ), data( d ) {
|
||||
}
|
||||
:
|
||||
node(n),
|
||||
key(k),
|
||||
weight(w),
|
||||
data(d)
|
||||
{ }
|
||||
|
||||
NodeID node;
|
||||
Key key;
|
||||
@ -234,14 +241,17 @@ private:
|
||||
const Key droppingIndex = heap[key].index;
|
||||
const Weight weight = heap[key].weight;
|
||||
Key nextKey = key << 1;
|
||||
while ( nextKey < static_cast<Key>( heap.size() ) ) {
|
||||
while( nextKey < static_cast<Key>( heap.size() ) ){
|
||||
const Key nextKeyOther = nextKey + 1;
|
||||
if ( ( nextKeyOther < static_cast<Key> ( heap.size() ) )&& ( heap[nextKey].weight > heap[nextKeyOther].weight) )
|
||||
if (
|
||||
( nextKeyOther < static_cast<Key>( heap.size() ) ) &&
|
||||
( heap[nextKey].weight > heap[nextKeyOther].weight )
|
||||
) {
|
||||
nextKey = nextKeyOther;
|
||||
|
||||
if ( weight <= heap[nextKey].weight )
|
||||
}
|
||||
if ( weight <= heap[nextKey].weight ){
|
||||
break;
|
||||
|
||||
}
|
||||
heap[key] = heap[nextKey];
|
||||
insertedNodes[heap[key].index].key = key;
|
||||
key = nextKey;
|
||||
@ -277,4 +287,4 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
#endif //#ifndef BINARYHEAP_H_INCLUDED
|
||||
#endif //BINARY_HEAP_H
|
||||
|
@ -25,34 +25,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include "../DataStructures/MercatorUtil.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <cmath>
|
||||
#include <climits>
|
||||
|
||||
#include <iostream>
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(INT_MIN),
|
||||
lon(INT_MIN)
|
||||
{ }
|
||||
|
||||
static const double COORDINATE_PRECISION = 1000000.;
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon)
|
||||
: lat(lat),
|
||||
lon(lon)
|
||||
{ }
|
||||
|
||||
struct FixedPointCoordinate {
|
||||
int lat;
|
||||
int lon;
|
||||
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {}
|
||||
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(lon) {}
|
||||
|
||||
void Reset() {
|
||||
void FixedPointCoordinate::Reset() {
|
||||
lat = INT_MIN;
|
||||
lon = INT_MIN;
|
||||
}
|
||||
bool isSet() const {
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const {
|
||||
return (INT_MIN != lat) && (INT_MIN != lon);
|
||||
}
|
||||
inline bool isValid() const {
|
||||
}
|
||||
bool FixedPointCoordinate::isValid() const {
|
||||
if(
|
||||
lat > 90*COORDINATE_PRECISION ||
|
||||
lat < -90*COORDINATE_PRECISION ||
|
||||
@ -62,18 +59,17 @@ struct FixedPointCoordinate {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator==(const FixedPointCoordinate & other) const {
|
||||
}
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate & other) const {
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
|
||||
out << "(" << c.lat << "," << c.lon << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
inline double ApproximateDistance( const int lat1, const int lon1, const int lat2, const int lon2 ) {
|
||||
double FixedPointCoordinate::ApproximateDistance(
|
||||
const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2
|
||||
) {
|
||||
BOOST_ASSERT(lat1 != INT_MIN);
|
||||
BOOST_ASSERT(lon1 != INT_MIN);
|
||||
BOOST_ASSERT(lat2 != INT_MIN);
|
||||
@ -94,18 +90,24 @@ inline double ApproximateDistance( const int lat1, const int lon1, const int lat
|
||||
|
||||
double aHarv= pow(sin(dLat/2.0),2.0)+cos(dlat1)*cos(dlat2)*pow(sin(dLong/2.),2);
|
||||
double cHarv=2.*atan2(sqrt(aHarv),sqrt(1.0-aHarv));
|
||||
//earth's radius from wikipedia varies between 6,356.750 km — 6,378.135 km (˜3,949.901 — 3,963.189 miles)
|
||||
//The IUGG value for the equatorial radius of the Earth is 6378.137 km (3963.19 mile)
|
||||
const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km
|
||||
//earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
//The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
const double earth=6372797.560856;
|
||||
double distance=earth*cHarv;
|
||||
return distance;
|
||||
}
|
||||
|
||||
inline double ApproximateDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||
double FixedPointCoordinate::ApproximateDistance(
|
||||
const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2
|
||||
) {
|
||||
return ApproximateDistance( c1.lat, c1.lon, c2.lat, c2.lon );
|
||||
}
|
||||
|
||||
inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const FixedPointCoordinate &c2) {
|
||||
double FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2
|
||||
) {
|
||||
BOOST_ASSERT(c1.lat != INT_MIN);
|
||||
BOOST_ASSERT(c1.lon != INT_MIN);
|
||||
BOOST_ASSERT(c2.lat != INT_MIN);
|
||||
@ -123,48 +125,38 @@ inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const
|
||||
return d;
|
||||
}
|
||||
|
||||
static inline void convertInternalLatLonToString(const int value, std::string & output) {
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(
|
||||
const int value,
|
||||
std::string & output
|
||||
) {
|
||||
char buffer[100];
|
||||
buffer[11] = 0; // zero termination
|
||||
char* string = printInt< 11, 6 >( buffer, value );
|
||||
output = string;
|
||||
}
|
||||
|
||||
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||
std::string tmp;
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
output += " ";
|
||||
}
|
||||
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
|
||||
std::string tmp;
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
output += " ";
|
||||
}
|
||||
|
||||
|
||||
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||
template<class CoordinateT>
|
||||
static inline double GetAngleBetweenThreeFixedPointCoordinates (
|
||||
const CoordinateT & A,
|
||||
const CoordinateT & C,
|
||||
const CoordinateT & B
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
) {
|
||||
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;
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
) {
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
@ -41,8 +41,8 @@ template< typename EdgeDataT>
|
||||
class DynamicGraph {
|
||||
public:
|
||||
typedef EdgeDataT EdgeData;
|
||||
typedef uint32_t NodeIterator;
|
||||
typedef uint32_t EdgeIterator;
|
||||
typedef unsigned NodeIterator;
|
||||
typedef unsigned EdgeIterator;
|
||||
|
||||
class InputEdge {
|
||||
public:
|
||||
@ -101,15 +101,15 @@ class DynamicGraph {
|
||||
|
||||
~DynamicGraph(){ }
|
||||
|
||||
uint32_t GetNumberOfNodes() const {
|
||||
unsigned GetNumberOfNodes() const {
|
||||
return m_numNodes;
|
||||
}
|
||||
|
||||
uint32_t GetNumberOfEdges() const {
|
||||
unsigned GetNumberOfEdges() const {
|
||||
return m_numEdges;
|
||||
}
|
||||
|
||||
uint32_t GetOutDegree( const NodeIterator n ) const {
|
||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
||||
return m_nodes[n].edges;
|
||||
}
|
||||
|
||||
@ -117,6 +117,10 @@ class DynamicGraph {
|
||||
return NodeIterator( m_edges[e].target );
|
||||
}
|
||||
|
||||
void SetTarget( const EdgeIterator e, const NodeIterator n ) {
|
||||
m_edges[e].target = n;
|
||||
}
|
||||
|
||||
EdgeDataT &GetEdgeData( const EdgeIterator e ) {
|
||||
return m_edges[e].data;
|
||||
}
|
||||
@ -143,7 +147,7 @@ class DynamicGraph {
|
||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
||||
} else {
|
||||
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
||||
uint32_t newSize = node.edges * 1.1 + 2;
|
||||
unsigned newSize = node.edges * 1.1 + 2;
|
||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
||||
EdgeIterator oldCapacity = m_edges.capacity();
|
||||
if ( requiredCapacity >= oldCapacity ) {
|
||||
@ -170,9 +174,12 @@ class DynamicGraph {
|
||||
//removes an edge. Invalidates edge iterators for the source node
|
||||
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
|
||||
Node &node = m_nodes[source];
|
||||
#pragma omp atomic
|
||||
--m_numEdges;
|
||||
--node.edges;
|
||||
const uint32_t last = node.firstEdge + node.edges;
|
||||
BOOST_ASSERT(UINT_MAX != node.edges);
|
||||
const unsigned last = node.firstEdge + node.edges;
|
||||
BOOST_ASSERT( UINT_MAX != last);
|
||||
//swap with last edge
|
||||
m_edges[e] = m_edges[last];
|
||||
makeDummy( last );
|
||||
@ -222,7 +229,7 @@ class DynamicGraph {
|
||||
//index of the first edge
|
||||
EdgeIterator firstEdge;
|
||||
//amount of edges
|
||||
uint32_t edges;
|
||||
unsigned edges;
|
||||
};
|
||||
|
||||
struct Edge {
|
||||
|
@ -1,9 +1,18 @@
|
||||
#ifndef EDGE_BASED_NODE_H
|
||||
#define EDGE_BASED_NODE_H
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
// An EdgeBasedNode represents a node in the edge-expanded graph.
|
||||
struct EdgeBasedNode {
|
||||
|
||||
EdgeBasedNode() :
|
||||
id(INT_MAX),
|
||||
lat1(INT_MAX),
|
||||
@ -16,6 +25,50 @@ struct EdgeBasedNode {
|
||||
ignoreInGrid(false)
|
||||
{ }
|
||||
|
||||
// Computes:
|
||||
// - the distance from the given query location to nearest point on this edge (and returns it)
|
||||
// - the location on this edge which is nearest to the query location
|
||||
// - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of
|
||||
// the query location on the line defined by p and q.
|
||||
double ComputePerpendicularDistance(
|
||||
const FixedPointCoordinate& query_location,
|
||||
FixedPointCoordinate & nearest_location,
|
||||
double & ratio,
|
||||
double precision = COORDINATE_PRECISION
|
||||
) const {
|
||||
BOOST_ASSERT( query_location.isValid() );
|
||||
|
||||
const double epsilon = 1.0/precision;
|
||||
|
||||
if( ignoreInGrid ) {
|
||||
return std::numeric_limits<double>::max();
|
||||
}
|
||||
|
||||
// p, q : the end points of the underlying edge
|
||||
const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION);
|
||||
const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION);
|
||||
|
||||
// r : query location
|
||||
const Point r(lat2y(query_location.lat/COORDINATE_PRECISION),
|
||||
query_location.lon/COORDINATE_PRECISION);
|
||||
|
||||
const Point foot = ComputePerpendicularFoot(p, q, r, epsilon);
|
||||
ratio = ComputeRatio(p, q, foot, epsilon);
|
||||
|
||||
BOOST_ASSERT( !std::isnan(ratio) );
|
||||
|
||||
nearest_location = ComputeNearestPointOnSegment(foot, ratio);
|
||||
|
||||
BOOST_ASSERT( nearest_location.isValid() );
|
||||
|
||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
|
||||
|
||||
BOOST_ASSERT( 0.0 <= approximated_distance );
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
bool operator<(const EdgeBasedNode & other) const {
|
||||
return other.id < id;
|
||||
}
|
||||
@ -24,28 +77,100 @@ struct EdgeBasedNode {
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
// Returns the midpoint of the underlying edge.
|
||||
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;
|
||||
return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2);
|
||||
}
|
||||
|
||||
NodeID id;
|
||||
|
||||
// The coordinates of the end-points of the underlying edge.
|
||||
int lat1;
|
||||
int lat2;
|
||||
int lon1;
|
||||
int lon2:31;
|
||||
|
||||
bool belongsToTinyComponent:1;
|
||||
NodeID nameID;
|
||||
|
||||
// The weight of the underlying edge.
|
||||
unsigned weight:31;
|
||||
|
||||
bool ignoreInGrid:1;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::pair<double,double> Point;
|
||||
|
||||
// Compute the perpendicular foot of point r on the line defined by p and q.
|
||||
Point ComputePerpendicularFoot(const Point &p, const Point &q, const Point &r, double epsilon) const {
|
||||
|
||||
// the projection of r onto the line pq
|
||||
double foot_x, foot_y;
|
||||
|
||||
const bool is_parallel_to_y_axis = std::abs(q.first - p.first) < epsilon;
|
||||
|
||||
if( is_parallel_to_y_axis ) {
|
||||
foot_x = q.first;
|
||||
foot_y = r.second;
|
||||
} else {
|
||||
// the slope of the line through (a|b) and (c|d)
|
||||
const double m = (q.second - p.second) / (q.first - p.first);
|
||||
|
||||
// Projection of (x|y) onto the line joining (a|b) and (c|d).
|
||||
foot_x = ((r.first + (m*r.second)) + (m*m*p.first - m*p.second))/(1.0 + m*m);
|
||||
foot_y = p.second + m*(foot_x - p.first);
|
||||
}
|
||||
|
||||
return Point(foot_x, foot_y);
|
||||
}
|
||||
|
||||
// Compute the ratio of the line segment pr to line segment pq.
|
||||
double ComputeRatio(const Point & p, const Point & q, const Point & r, double epsilon) const {
|
||||
|
||||
const bool is_parallel_to_x_axis = std::abs(q.second-p.second) < epsilon;
|
||||
const bool is_parallel_to_y_axis = std::abs(q.first -p.first ) < epsilon;
|
||||
|
||||
double ratio;
|
||||
|
||||
if( !is_parallel_to_y_axis ) {
|
||||
ratio = (r.first - p.first)/(q.first - p.first);
|
||||
} else if( !is_parallel_to_x_axis ) {
|
||||
ratio = (r.second - p.second)/(q.second - p.second);
|
||||
} else {
|
||||
// (a|b) and (c|d) are essentially the same point
|
||||
// by convention, we set the ratio to 0 in this case
|
||||
//ratio = ((lat2 == query_location.lat) && (lon2 == query_location.lon)) ? 1. : 0.;
|
||||
ratio = 0.0;
|
||||
}
|
||||
|
||||
// Round to integer if the ratio is close to 0 or 1.
|
||||
if( std::abs(ratio) <= epsilon ) {
|
||||
ratio = 0.0;
|
||||
} else if( std::abs(ratio-1.0) <= epsilon ) {
|
||||
ratio = 1.0;
|
||||
}
|
||||
|
||||
return ratio;
|
||||
}
|
||||
|
||||
// Computes the point on the segment pq which is nearest to a point r = p + lambda * (q-p).
|
||||
// p and q are the end points of the underlying edge.
|
||||
FixedPointCoordinate ComputeNearestPointOnSegment(const Point & r, double lambda) const {
|
||||
|
||||
if( lambda <= 0.0 ) {
|
||||
return FixedPointCoordinate(lat1, lon1);
|
||||
} else if( lambda >= 1.0 ) {
|
||||
return FixedPointCoordinate(lat2, lon2);
|
||||
}
|
||||
|
||||
// r lies between p and q
|
||||
return FixedPointCoordinate(
|
||||
y2lat(r.first)*COORDINATE_PRECISION,
|
||||
r.second*COORDINATE_PRECISION
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif //EDGE_BASED_NODE_H
|
@ -25,43 +25,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HASHTABLE_H_
|
||||
#define HASHTABLE_H_
|
||||
#ifndef HASH_TABLE_H
|
||||
#define HASH_TABLE_H
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
template<typename keyT, typename valueT>
|
||||
class HashTable : public boost::unordered_map<keyT, valueT> {
|
||||
template<typename KeyT, typename ValueT>
|
||||
class HashTable : public boost::unordered_map<KeyT, ValueT> {
|
||||
private:
|
||||
typedef boost::unordered_map<keyT, valueT> super;
|
||||
typedef boost::unordered_map<KeyT, ValueT> super;
|
||||
public:
|
||||
static ValueT default_value;
|
||||
|
||||
HashTable() : super() { }
|
||||
|
||||
HashTable(const unsigned size) : super(size) { }
|
||||
|
||||
HashTable &operator=(const HashTable &other) {
|
||||
super::operator = (other);
|
||||
return *this;
|
||||
inline void Add( KeyT const & key, ValueT const & value) {
|
||||
super::emplace(std::make_pair(key, value));
|
||||
}
|
||||
|
||||
inline void Add(const keyT& key, const valueT& value){
|
||||
super::insert(std::make_pair(key, value));
|
||||
inline const ValueT Find(KeyT const & key) const {
|
||||
typename super::const_iterator iter = super::find(key);
|
||||
if( iter == super::end() ) {
|
||||
return boost::cref(default_value);
|
||||
}
|
||||
return boost::cref(iter->second);
|
||||
}
|
||||
|
||||
inline valueT Find(const keyT& key) const {
|
||||
if(super::find(key) == super::end()) {
|
||||
return valueT();
|
||||
}
|
||||
return boost::ref(super::find(key)->second);
|
||||
}
|
||||
|
||||
inline bool Holds(const keyT& key) const {
|
||||
if(super::find(key) == super::end()) {
|
||||
inline bool Holds( KeyT const & key) const {
|
||||
if( super::find(key) == super::end() ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* HASHTABLE_H_ */
|
||||
template<typename KeyT, typename ValueT>
|
||||
ValueT HashTable<KeyT, ValueT>::default_value;
|
||||
|
||||
#endif /* HASH_TABLE_H */
|
||||
|
88
DataStructures/HilbertValue.cpp
Normal file
88
DataStructures/HilbertValue.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "HilbertValue.h"
|
||||
|
||||
uint64_t HilbertCode::operator() (
|
||||
const FixedPointCoordinate & current_coordinate
|
||||
) const {
|
||||
unsigned location[2];
|
||||
location[0] = current_coordinate.lat+( 90*COORDINATE_PRECISION);
|
||||
location[1] = current_coordinate.lon+(180*COORDINATE_PRECISION);
|
||||
|
||||
TransposeCoordinate(location);
|
||||
return BitInterleaving(location[0], location[1]);
|
||||
}
|
||||
|
||||
uint64_t HilbertCode::BitInterleaving(const uint32_t latitude, const uint32_t longitude) const
|
||||
{
|
||||
uint64_t result = 0;
|
||||
for(int8_t index = 31; index >= 0; --index){
|
||||
result |= (latitude >> index) & 1;
|
||||
result <<= 1;
|
||||
result |= (longitude >> index) & 1;
|
||||
if(0 != index){
|
||||
result <<= 1;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void HilbertCode::TransposeCoordinate( uint32_t * X) const
|
||||
{
|
||||
uint32_t M = 1 << (32-1), P, Q, t;
|
||||
int i;
|
||||
// Inverse undo
|
||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||
P=Q-1;
|
||||
for( i = 0; i < 2; ++i ) {
|
||||
|
||||
const bool condition = (X[i] & Q);
|
||||
if( condition ) {
|
||||
X[0] ^= P; // invert
|
||||
} else {
|
||||
t = (X[0]^X[i]) & P;
|
||||
X[0] ^= t;
|
||||
X[i] ^= t;
|
||||
}
|
||||
} // exchange
|
||||
}
|
||||
// Gray encode
|
||||
for( i = 1; i < 2; ++i ) {
|
||||
X[i] ^= X[i-1];
|
||||
}
|
||||
t=0;
|
||||
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||
const bool condition = (X[2-1] & Q);
|
||||
if( condition ) {
|
||||
t ^= Q-1;
|
||||
}
|
||||
} //check if this for loop is wrong
|
||||
for( i = 0; i < 2; ++i ) {
|
||||
X[i] ^= t;
|
||||
}
|
||||
}
|
@ -28,70 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef HILBERTVALUE_H_
|
||||
#define HILBERTVALUE_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include <osrm/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 {
|
||||
class HilbertCode : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
static uint64_t GetHilbertNumberForCoordinate(
|
||||
uint64_t operator()
|
||||
(
|
||||
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;
|
||||
}
|
||||
) const;
|
||||
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;
|
||||
}
|
||||
}
|
||||
inline uint64_t BitInterleaving( const uint32_t a, const uint32_t b) const;
|
||||
inline void TransposeCoordinate( uint32_t * X) const;
|
||||
};
|
||||
|
||||
#endif /* HILBERTVALUE_H_ */
|
||||
|
58
DataStructures/OriginalEdgeData.h
Normal file
58
DataStructures/OriginalEdgeData.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ORIGINAL_EDGE_DATA_H
|
||||
#define ORIGINAL_EDGE_DATA_H
|
||||
|
||||
#include "TurnInstructions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
struct OriginalEdgeData{
|
||||
explicit OriginalEdgeData(
|
||||
NodeID via_node,
|
||||
unsigned name_id,
|
||||
TurnInstruction turn_instruction
|
||||
) :
|
||||
via_node(via_node),
|
||||
name_id(name_id),
|
||||
turn_instruction(turn_instruction)
|
||||
{ }
|
||||
|
||||
OriginalEdgeData() :
|
||||
via_node(UINT_MAX),
|
||||
name_id(UINT_MAX),
|
||||
turn_instruction(UCHAR_MAX)
|
||||
{ }
|
||||
|
||||
NodeID via_node;
|
||||
unsigned name_id;
|
||||
TurnInstruction turn_instruction;
|
||||
};
|
||||
|
||||
#endif //ORIGINAL_EDGE_DATA_H
|
@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef PHANTOMNODES_H_
|
||||
#define PHANTOMNODES_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
struct PhantomNode {
|
||||
PhantomNode() :
|
||||
|
@ -28,23 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef QUERYEDGE_H_
|
||||
#define QUERYEDGE_H_
|
||||
|
||||
#include "TurnInstructions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
|
||||
struct OriginalEdgeData{
|
||||
explicit OriginalEdgeData(
|
||||
NodeID viaNode,
|
||||
unsigned nameID,
|
||||
TurnInstruction turnInstruction
|
||||
) : viaNode(viaNode), nameID(nameID), turnInstruction(turnInstruction) {}
|
||||
OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {}
|
||||
NodeID viaNode;
|
||||
unsigned nameID;
|
||||
TurnInstruction turnInstruction;
|
||||
};
|
||||
|
||||
struct QueryEdge {
|
||||
NodeID source;
|
||||
NodeID target;
|
||||
@ -64,9 +51,14 @@ struct QueryEdge {
|
||||
}
|
||||
|
||||
bool operator== ( const QueryEdge& right ) const {
|
||||
return ( source == right.source && target == right.target && data.distance == right.data.distance &&
|
||||
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward
|
||||
&& data.id == right.data.id
|
||||
return (
|
||||
source == right.source &&
|
||||
target == right.target &&
|
||||
data.distance == right.data.distance &&
|
||||
data.shortcut == right.data.shortcut &&
|
||||
data.forward == right.data.forward &&
|
||||
data.backward == right.data.backward &&
|
||||
data.id == right.data.id
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -28,9 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef _NODE_COORDS_H
|
||||
#define _NODE_COORDS_H
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
|
@ -28,29 +28,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef RAWROUTEDATA_H_
|
||||
#define RAWROUTEDATA_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct _PathData {
|
||||
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
||||
struct PathData {
|
||||
PathData() :
|
||||
node(UINT_MAX),
|
||||
name_id(UINT_MAX),
|
||||
durationOfSegment(UINT_MAX),
|
||||
turnInstruction(UCHAR_MAX)
|
||||
{ }
|
||||
|
||||
PathData(
|
||||
NodeID no,
|
||||
unsigned na,
|
||||
unsigned tu,
|
||||
unsigned dur
|
||||
) :
|
||||
node(no),
|
||||
name_id(na),
|
||||
durationOfSegment(dur),
|
||||
turnInstruction(tu)
|
||||
{ }
|
||||
NodeID node;
|
||||
unsigned nameID;
|
||||
unsigned name_id;
|
||||
unsigned durationOfSegment;
|
||||
short turnInstruction;
|
||||
};
|
||||
|
||||
struct RawRouteData {
|
||||
std::vector< _PathData > computedShortestPath;
|
||||
std::vector< _PathData > computedAlternativePath;
|
||||
std::vector< std::vector<PathData> > unpacked_path_segments;
|
||||
std::vector< PathData > unpacked_alternative;
|
||||
std::vector< PhantomNodes > segmentEndCoordinates;
|
||||
std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
|
||||
unsigned checkSum;
|
||||
int lengthOfShortestPath;
|
||||
int lengthOfAlternativePath;
|
||||
RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), lengthOfAlternativePath(INT_MAX) {}
|
||||
RawRouteData() :
|
||||
checkSum(UINT_MAX),
|
||||
lengthOfShortestPath(INT_MAX),
|
||||
lengthOfAlternativePath(INT_MAX)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* RAWROUTEDATA_H_ */
|
||||
|
@ -105,13 +105,16 @@ struct InputRestrictionContainer {
|
||||
return InputRestrictionContainer(0, 0, 0, 0);
|
||||
}
|
||||
static InputRestrictionContainer max_value() {
|
||||
return InputRestrictionContainer(UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX);
|
||||
return InputRestrictionContainer(
|
||||
UINT_MAX,
|
||||
UINT_MAX,
|
||||
UINT_MAX,
|
||||
UINT_MAX
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpRestrictionContainerByFrom :
|
||||
public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool>
|
||||
{
|
||||
struct CmpRestrictionContainerByFrom {
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator()(
|
||||
const InputRestrictionContainer & a,
|
||||
@ -127,9 +130,9 @@ struct CmpRestrictionContainerByFrom :
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpRestrictionContainerByTo: public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool> {
|
||||
struct CmpRestrictionContainerByTo {
|
||||
typedef InputRestrictionContainer value_type;
|
||||
inline bool operator ()(
|
||||
inline bool operator()(
|
||||
const InputRestrictionContainer & a,
|
||||
const InputRestrictionContainer & b
|
||||
) const {
|
||||
|
@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SEARCHENGINE_H
|
||||
#define SEARCHENGINE_H
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "SearchEngineData.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "QueryEdge.h"
|
||||
@ -38,6 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <climits>
|
||||
|
@ -27,41 +27,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "SearchEngineData.h"
|
||||
|
||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) {
|
||||
if(!forwardHeap.get()) {
|
||||
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
} else {
|
||||
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap.get())
|
||||
{
|
||||
forwardHeap->Clear();
|
||||
}
|
||||
if(!backwardHeap.get()) {
|
||||
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
} else {
|
||||
else
|
||||
{
|
||||
forwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap.get())
|
||||
{
|
||||
backwardHeap->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) {
|
||||
if(!forwardHeap2.get()) {
|
||||
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
} else {
|
||||
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap2.get())
|
||||
{
|
||||
forwardHeap2->Clear();
|
||||
}
|
||||
if(!backwardHeap2.get()) {
|
||||
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
} else {
|
||||
else
|
||||
{
|
||||
forwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap2.get())
|
||||
{
|
||||
backwardHeap2->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap2.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) {
|
||||
if(!forwardHeap3.get()) {
|
||||
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
} else {
|
||||
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
|
||||
{
|
||||
if (forwardHeap3.get())
|
||||
{
|
||||
forwardHeap3->Clear();
|
||||
}
|
||||
if(!backwardHeap3.get()) {
|
||||
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
} else {
|
||||
else
|
||||
{
|
||||
forwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
|
||||
if (backwardHeap3.get())
|
||||
{
|
||||
backwardHeap3->Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
backwardHeap3.reset(new QueryHeap(number_of_nodes));
|
||||
}
|
||||
}
|
||||
|
@ -28,24 +28,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SEGMENTINFORMATION_H_
|
||||
#define SEGMENTINFORMATION_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "TurnInstructions.h"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <climits>
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
// Struct fits everything in one cache line
|
||||
struct SegmentInformation {
|
||||
FixedPointCoordinate location;
|
||||
NodeID nameID;
|
||||
double length;
|
||||
NodeID name_id;
|
||||
unsigned duration;
|
||||
double bearing;
|
||||
TurnInstruction turnInstruction;
|
||||
double length;
|
||||
short bearing; //more than enough [0..3600] fits into 12 bits
|
||||
TurnInstruction turn_instruction;
|
||||
bool necessary;
|
||||
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) {}
|
||||
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) {}
|
||||
|
||||
explicit SegmentInformation(
|
||||
const FixedPointCoordinate & location,
|
||||
const NodeID name_id,
|
||||
const unsigned duration,
|
||||
const double length,
|
||||
const TurnInstruction turn_instruction,
|
||||
const bool necessary
|
||||
) :
|
||||
location(location),
|
||||
name_id(name_id),
|
||||
duration(duration),
|
||||
length(length),
|
||||
bearing(0),
|
||||
turn_instruction(turn_instruction),
|
||||
necessary(necessary)
|
||||
{ }
|
||||
|
||||
explicit SegmentInformation(
|
||||
const FixedPointCoordinate & location,
|
||||
const NodeID name_id,
|
||||
const unsigned duration,
|
||||
const double length,
|
||||
const TurnInstruction turn_instruction
|
||||
) :
|
||||
location(location),
|
||||
name_id(name_id),
|
||||
duration(duration),
|
||||
length(length),
|
||||
bearing(0),
|
||||
turn_instruction(turn_instruction),
|
||||
necessary(turn_instruction != 0)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* SEGMENTINFORMATION_H_ */
|
||||
|
@ -28,19 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef STATICRTREE_H_
|
||||
#define STATICRTREE_H_
|
||||
|
||||
#include "Coordinate.h"
|
||||
#include "DeallocatingVector.h"
|
||||
#include "HilbertValue.h"
|
||||
#include "MercatorUtil.h"
|
||||
#include "PhantomNodes.h"
|
||||
#include "SharedMemoryFactory.h"
|
||||
#include "SharedMemoryVectorWrapper.h"
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
@ -124,10 +125,10 @@ public:
|
||||
FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
|
||||
|
||||
return (
|
||||
Contains(upper_left)
|
||||
|| Contains(upper_right)
|
||||
|| Contains(lower_right)
|
||||
|| Contains(lower_left)
|
||||
Contains(upper_left ) ||
|
||||
Contains(upper_right) ||
|
||||
Contains(lower_right) ||
|
||||
Contains(lower_left )
|
||||
);
|
||||
}
|
||||
|
||||
@ -140,7 +141,7 @@ public:
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
max_lat,
|
||||
@ -149,7 +150,7 @@ public:
|
||||
);
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
max_lat,
|
||||
@ -158,7 +159,7 @@ public:
|
||||
);
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
min_lat,
|
||||
@ -167,7 +168,7 @@ public:
|
||||
);
|
||||
min_dist = std::min(
|
||||
min_dist,
|
||||
ApproximateDistance(
|
||||
FixedPointCoordinate::ApproximateDistance(
|
||||
location.lat,
|
||||
location.lon,
|
||||
min_lat,
|
||||
@ -188,32 +189,32 @@ public:
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, upper_left ),
|
||||
ApproximateDistance(location, upper_right)
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_left ),
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_right)
|
||||
)
|
||||
);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, upper_right),
|
||||
ApproximateDistance(location, lower_right)
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_right),
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_right)
|
||||
)
|
||||
);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, lower_right),
|
||||
ApproximateDistance(location, lower_left )
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_right),
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_left )
|
||||
)
|
||||
);
|
||||
|
||||
min_max_dist = std::min(
|
||||
min_max_dist,
|
||||
std::max(
|
||||
ApproximateDistance(location, lower_left ),
|
||||
ApproximateDistance(location, upper_left )
|
||||
FixedPointCoordinate::ApproximateDistance(location, lower_left ),
|
||||
FixedPointCoordinate::ApproximateDistance(location, upper_left )
|
||||
)
|
||||
);
|
||||
return min_max_dist;
|
||||
@ -307,6 +308,8 @@ public:
|
||||
double time1 = get_timestamp();
|
||||
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
|
||||
|
||||
HilbertCode get_hilbert_number;
|
||||
|
||||
//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) {
|
||||
@ -316,10 +319,10 @@ public:
|
||||
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);
|
||||
uint64_t current_hilbert_value = get_hilbert_number(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));
|
||||
@ -334,6 +337,7 @@ public:
|
||||
|
||||
LeafNode current_leaf;
|
||||
TreeNode current_node;
|
||||
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
|
||||
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;
|
||||
@ -391,6 +395,7 @@ public:
|
||||
|
||||
//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];
|
||||
@ -435,7 +440,7 @@ public:
|
||||
|
||||
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();
|
||||
@ -526,12 +531,10 @@ public:
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
input_coordinate,
|
||||
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||
nearest,
|
||||
¤t_ratio
|
||||
current_ratio
|
||||
);
|
||||
|
||||
if(
|
||||
@ -556,7 +559,7 @@ public:
|
||||
} else if(
|
||||
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||
&& CoordinatesAreEquivalent(
|
||||
&& EdgesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
@ -675,11 +678,8 @@ public:
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if(current_edge.isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_minimum_distance = ApproximateDistance(
|
||||
double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat1,
|
||||
@ -693,7 +693,7 @@ public:
|
||||
found_a_nearest_edge = true;
|
||||
}
|
||||
|
||||
current_minimum_distance = ApproximateDistance(
|
||||
current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
current_edge.lat2,
|
||||
@ -736,7 +736,6 @@ public:
|
||||
return found_a_nearest_edge;
|
||||
}
|
||||
|
||||
|
||||
bool FindPhantomNodeForCoordinate(
|
||||
const FixedPointCoordinate & input_coordinate,
|
||||
PhantomNode & result_phantom_node,
|
||||
@ -746,7 +745,7 @@ public:
|
||||
bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
|
||||
uint32_t io_count = 0;
|
||||
// uint32_t io_count = 0;
|
||||
uint32_t explored_tree_nodes_count = 0;
|
||||
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
@ -758,15 +757,14 @@ public:
|
||||
//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)
|
||||
);
|
||||
traversal_queue.push( QueryCandidate(0, current_min_dist) );
|
||||
|
||||
BOOST_ASSERT_MSG(
|
||||
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
|
||||
"Root element in NN Search has min dist != 0."
|
||||
);
|
||||
|
||||
LeafNode current_leaf_node;
|
||||
while(!traversal_queue.empty()) {
|
||||
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||
|
||||
@ -776,30 +774,26 @@ public:
|
||||
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;
|
||||
// ++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;
|
||||
}
|
||||
if(current_edge.isIgnored()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||
double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
|
||||
input_coordinate,
|
||||
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
|
||||
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
|
||||
nearest,
|
||||
¤t_ratio
|
||||
current_ratio
|
||||
);
|
||||
|
||||
BOOST_ASSERT( 0. <= current_perpendicular_distance );
|
||||
|
||||
if(
|
||||
current_perpendicular_distance < min_dist
|
||||
&& !DoubleEpsilonCompare(
|
||||
( current_perpendicular_distance < min_dist ) &&
|
||||
!DoubleEpsilonCompare(
|
||||
current_perpendicular_distance,
|
||||
min_dist
|
||||
)
|
||||
@ -816,10 +810,10 @@ public:
|
||||
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(
|
||||
} else
|
||||
if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||
( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) &&
|
||||
EdgesAreEquivalent(
|
||||
current_start_coordinate,
|
||||
FixedPointCoordinate(
|
||||
current_edge.lat1,
|
||||
@ -853,10 +847,10 @@ public:
|
||||
if( current_min_max_dist < min_max_dist ) {
|
||||
min_max_dist = current_min_max_dist;
|
||||
}
|
||||
if (current_min_dist > min_max_dist) {
|
||||
if( current_min_dist > min_max_dist ) {
|
||||
continue;
|
||||
}
|
||||
if (current_min_dist > min_dist) { //upward pruning
|
||||
if( current_min_dist > min_dist ) { //upward pruning
|
||||
continue;
|
||||
}
|
||||
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||
@ -865,17 +859,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -884,8 +867,30 @@ public:
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
return found_a_nearest_edge;
|
||||
double ratio = 0.;
|
||||
|
||||
if( found_a_nearest_edge) {
|
||||
const double distance_1 = FixedPointCoordinate::ApproximateDistance(
|
||||
current_start_coordinate,
|
||||
result_phantom_node.location
|
||||
);
|
||||
|
||||
const double distance_2 = FixedPointCoordinate::ApproximateDistance(
|
||||
current_start_coordinate,
|
||||
current_end_coordinate
|
||||
);
|
||||
|
||||
ratio = distance_1/distance_2;
|
||||
ratio = std::min(1., ratio);
|
||||
}
|
||||
|
||||
result_phantom_node.weight1 *= ratio;
|
||||
if(INT_MAX != result_phantom_node.weight2) {
|
||||
result_phantom_node.weight2 *= (1.-ratio);
|
||||
}
|
||||
result_phantom_node.ratio = ratio;
|
||||
|
||||
return found_a_nearest_edge;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -910,60 +915,17 @@ private:
|
||||
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 = inputPoint.lat/COORDINATE_PRECISION;
|
||||
const double y = inputPoint.lon/COORDINATE_PRECISION;
|
||||
const double a = source.lat/COORDINATE_PRECISION;
|
||||
const double b = source.lon/COORDINATE_PRECISION;
|
||||
const double c = target.lat/COORDINATE_PRECISION;
|
||||
const double d = target.lon/COORDINATE_PRECISION;
|
||||
double p,q,mX,nY;
|
||||
if(std::fabs(a-c) > std::numeric_limits<double>::epsilon() ){
|
||||
const double m = (d-b)/(c-a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||
q = b + m*(p - a);
|
||||
} else {
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d*p - c*q)/(a*d - b*c);
|
||||
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*COORDINATE_PRECISION;
|
||||
nearest.lon = q*COORDINATE_PRECISION;
|
||||
// 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 {
|
||||
inline bool EdgesAreEquivalent(
|
||||
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) < std::numeric_limits<double>::epsilon() );
|
||||
return (std::abs(d1 - d2) < std::numeric_limits<double>::epsilon() );
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -28,15 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASE_DESCRIPTOR_H_
|
||||
#define BASE_DESCRIPTOR_H_
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../DataStructures/RawRouteData.h"
|
||||
#include "../Server/Http/Reply.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -61,10 +57,10 @@ public:
|
||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() { }
|
||||
virtual void Run(
|
||||
http::Reply & reply,
|
||||
const RawRouteData &rawRoute,
|
||||
PhantomNodes &phantomNodes,
|
||||
const DataFacadeT * facade
|
||||
const RawRouteData & rawRoute,
|
||||
const PhantomNodes & phantomNodes,
|
||||
DataFacadeT * facade,
|
||||
http::Reply & reply
|
||||
) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig & config) = 0;
|
||||
};
|
||||
|
@ -43,13 +43,13 @@ double DescriptionFactory::GetBearing(
|
||||
const FixedPointCoordinate & A,
|
||||
const FixedPointCoordinate & B
|
||||
) const {
|
||||
double deltaLong = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION);
|
||||
|
||||
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
|
||||
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
|
||||
|
||||
const double y = sin(deltaLong) * cos(lat2);
|
||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong);
|
||||
const double y = sin(delta_long) * cos(lat2);
|
||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
||||
double result = RadianToDegree(atan2(y, x));
|
||||
while(result < 0.) {
|
||||
result += 360.;
|
||||
@ -60,22 +60,22 @@ double DescriptionFactory::GetBearing(
|
||||
return result;
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode & sph) {
|
||||
start_phantom = sph;
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode & start) {
|
||||
start_phantom = start;
|
||||
AppendSegment(
|
||||
sph.location,
|
||||
_PathData(0, sph.nodeBasedEdgeNameID, 10, sph.weight1)
|
||||
start.location,
|
||||
PathData(0, start.nodeBasedEdgeNameID, 10, start.weight1)
|
||||
);
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetEndSegment(const PhantomNode & tph) {
|
||||
target_phantom = tph;
|
||||
void DescriptionFactory::SetEndSegment(const PhantomNode & target) {
|
||||
target_phantom = target;
|
||||
pathDescription.push_back(
|
||||
SegmentInformation(
|
||||
tph.location,
|
||||
tph.nodeBasedEdgeNameID,
|
||||
target.location,
|
||||
target.nodeBasedEdgeNameID,
|
||||
0,
|
||||
tph.weight1,
|
||||
target.weight1,
|
||||
0,
|
||||
true
|
||||
)
|
||||
@ -84,12 +84,23 @@ void DescriptionFactory::SetEndSegment(const PhantomNode & tph) {
|
||||
|
||||
void DescriptionFactory::AppendSegment(
|
||||
const FixedPointCoordinate & coordinate,
|
||||
const _PathData & data
|
||||
const PathData & data
|
||||
) {
|
||||
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) {
|
||||
pathDescription.back().nameID = data.nameID;
|
||||
if(
|
||||
( 1 == pathDescription.size()) &&
|
||||
( pathDescription.back().location == coordinate)
|
||||
) {
|
||||
pathDescription.back().name_id = data.name_id;
|
||||
} else {
|
||||
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
|
||||
pathDescription.push_back(
|
||||
SegmentInformation(
|
||||
coordinate,
|
||||
data.name_id,
|
||||
data.durationOfSegment,
|
||||
0,
|
||||
data.turnInstruction
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,127 +133,6 @@ void DescriptionFactory::AppendUnencodedPolylineString(
|
||||
output.push_back(temp);
|
||||
}
|
||||
|
||||
// void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
||||
|
||||
// if(0 == pathDescription.size())
|
||||
// return;
|
||||
|
||||
// // unsigned entireLength = 0;
|
||||
// /** starts at index 1 */
|
||||
// pathDescription[0].length = 0;
|
||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
// pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||
// }
|
||||
|
||||
// double lengthOfSegment = 0;
|
||||
// unsigned durationOfSegment = 0;
|
||||
// unsigned indexOfSegmentBegin = 0;
|
||||
|
||||
// std::string string0 = sEngine.GetEscapedNameForNameID(pathDescription[0].nameID);
|
||||
// std::string string1;
|
||||
|
||||
|
||||
// /*Simplify turn instructions
|
||||
// Input :
|
||||
// 10. Turn left on B 36 for 20 km
|
||||
// 11. Continue on B 35; B 36 for 2 km
|
||||
// 12. Continue on B 36 for 13 km
|
||||
|
||||
// becomes:
|
||||
// 10. Turn left on B 36 for 35 km
|
||||
// */
|
||||
// //TODO: rework to check only end and start of string.
|
||||
// // stl string is way to expensive
|
||||
|
||||
// // unsigned lastTurn = 0;
|
||||
// // for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
// // string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||
// // if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||
// // if(std::string::npos != string0.find(string1+";")
|
||||
// // || std::string::npos != string0.find(";"+string1)
|
||||
// // || std::string::npos != string0.find(string1+" ;")
|
||||
// // || std::string::npos != string0.find("; "+string1)
|
||||
// // ){
|
||||
// // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||
// // for(; lastTurn != i; ++lastTurn)
|
||||
// // pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// // } else if(std::string::npos != string1.find(string0+";")
|
||||
// // || std::string::npos != string1.find(";"+string0)
|
||||
// // || std::string::npos != string1.find(string0+" ;")
|
||||
// // || std::string::npos != string1.find("; "+string0)
|
||||
// // ){
|
||||
// // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||
// // pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||
// // pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// // }
|
||||
// // }
|
||||
// // if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
// // lastTurn = i;
|
||||
// // }
|
||||
// // string0 = string1;
|
||||
// // }
|
||||
|
||||
|
||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
// entireLength += pathDescription[i].length;
|
||||
// lengthOfSegment += pathDescription[i].length;
|
||||
// durationOfSegment += pathDescription[i].duration;
|
||||
// pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||
// pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||
|
||||
|
||||
// if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
// //SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID;
|
||||
// assert(pathDescription[i].necessary);
|
||||
// lengthOfSegment = 0;
|
||||
// durationOfSegment = 0;
|
||||
// indexOfSegmentBegin = i;
|
||||
// }
|
||||
// }
|
||||
// // SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||
|
||||
// //Post-processing to remove empty or nearly empty path segments
|
||||
// if(FLT_EPSILON > pathDescription.back().length) {
|
||||
// // SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
||||
// if(pathDescription.size() > 2){
|
||||
// pathDescription.pop_back();
|
||||
// pathDescription.back().necessary = true;
|
||||
// pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||
// target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||
// // SimpleLogger().Write() << "Deleting last turn instruction";
|
||||
// }
|
||||
// } else {
|
||||
// pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||
// }
|
||||
// if(FLT_EPSILON > pathDescription[0].length) {
|
||||
// //TODO: this is never called actually?
|
||||
// if(pathDescription.size() > 2) {
|
||||
// pathDescription.erase(pathDescription.begin());
|
||||
// pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||
// pathDescription[0].necessary = true;
|
||||
// start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||
// // SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
||||
// }
|
||||
// } else {
|
||||
// pathDescription[0].duration *= start_phantom.ratio;
|
||||
// }
|
||||
|
||||
// //Generalize poly line
|
||||
// dp.Run(pathDescription, zoomLevel);
|
||||
|
||||
// //fix what needs to be fixed else
|
||||
// for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||
// if(pathDescription[i].necessary) {
|
||||
// double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||
// pathDescription[i].bearing = angle;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // BuildRouteSummary(entireLength, duration);
|
||||
// return;
|
||||
// }
|
||||
|
||||
void DescriptionFactory::BuildRouteSummary(
|
||||
const double distance,
|
||||
const unsigned time
|
||||
|
@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../Algorithms/DouglasPeucker.h"
|
||||
#include "../Algorithms/PolylineCompressor.h"
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../DataStructures/RawRouteData.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
@ -38,6 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
@ -70,8 +71,8 @@ public:
|
||||
) {
|
||||
//compute distance/duration for route summary
|
||||
intToString(round(distance), lengthString);
|
||||
int travelTime = time/10 + 1;
|
||||
intToString(travelTime, durationString);
|
||||
int travel_time = time/10;
|
||||
intToString(std::max(travel_time, 1), durationString);
|
||||
}
|
||||
} summary;
|
||||
|
||||
@ -84,7 +85,7 @@ public:
|
||||
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
|
||||
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data);
|
||||
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
|
||||
void BuildRouteSummary(const double distance, const unsigned time);
|
||||
void SetStartSegment(const PhantomNode & start_phantom);
|
||||
void SetEndSegment(const PhantomNode & start_phantom);
|
||||
@ -94,24 +95,21 @@ public:
|
||||
);
|
||||
|
||||
template<class DataFacadeT>
|
||||
void Run(const DataFacadeT * facade, const unsigned zoomLevel) {
|
||||
|
||||
void Run(
|
||||
const DataFacadeT * facade,
|
||||
const unsigned zoomLevel
|
||||
) {
|
||||
if( pathDescription.empty() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// unsigned entireLength = 0;
|
||||
/** starts at index 1 */
|
||||
pathDescription[0].length = 0;
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
pathDescription[i].length = ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||
}
|
||||
|
||||
double lengthOfSegment = 0;
|
||||
unsigned durationOfSegment = 0;
|
||||
unsigned indexOfSegmentBegin = 0;
|
||||
|
||||
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].nameID);
|
||||
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].name_id);
|
||||
// std::string string1;
|
||||
|
||||
|
||||
@ -129,8 +127,8 @@ public:
|
||||
|
||||
// unsigned lastTurn = 0;
|
||||
// for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID);
|
||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) {
|
||||
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id);
|
||||
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) {
|
||||
// if(std::string::npos != string0.find(string1+";")
|
||||
// || std::string::npos != string0.find(";"+string1)
|
||||
// || std::string::npos != string0.find(string1+" ;")
|
||||
@ -138,24 +136,27 @@ public:
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
|
||||
// for(; lastTurn != i; ++lastTurn)
|
||||
// pathDescription[lastTurn].nameID = pathDescription[i].nameID;
|
||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// pathDescription[lastTurn].name_id = pathDescription[i].name_id;
|
||||
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
|
||||
// } else if(std::string::npos != string1.find(string0+";")
|
||||
// || std::string::npos != string1.find(";"+string0)
|
||||
// || std::string::npos != string1.find(string0+" ;")
|
||||
// || std::string::npos != string1.find("; "+string0)
|
||||
// ){
|
||||
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
|
||||
// pathDescription[i].nameID = pathDescription[i-1].nameID;
|
||||
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn;
|
||||
// pathDescription[i].name_id = pathDescription[i-1].name_id;
|
||||
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
|
||||
// }
|
||||
// }
|
||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
||||
// lastTurn = i;
|
||||
// }
|
||||
// string0 = string1;
|
||||
// }
|
||||
|
||||
double lengthOfSegment = 0;
|
||||
unsigned durationOfSegment = 0;
|
||||
unsigned indexOfSegmentBegin = 0;
|
||||
|
||||
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||
entireLength += pathDescription[i].length;
|
||||
@ -165,37 +166,31 @@ public:
|
||||
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||
|
||||
|
||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) {
|
||||
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << pathDescription[i].nameID;
|
||||
assert(pathDescription[i].necessary);
|
||||
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
|
||||
BOOST_ASSERT(pathDescription[i].necessary);
|
||||
lengthOfSegment = 0;
|
||||
durationOfSegment = 0;
|
||||
indexOfSegmentBegin = i;
|
||||
}
|
||||
}
|
||||
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
|
||||
|
||||
//Post-processing to remove empty or nearly empty path segments
|
||||
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) {
|
||||
// SimpleLogger().Write() << "#segs: " << pathDescription.size() << ", last ratio: " << target_phantom.ratio << ", length: " << pathDescription.back().length;
|
||||
if(pathDescription.size() > 2){
|
||||
pathDescription.pop_back();
|
||||
pathDescription.back().necessary = true;
|
||||
pathDescription.back().turnInstruction = TurnInstructions.NoTurn;
|
||||
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID;
|
||||
// SimpleLogger().Write() << "Deleting last turn instruction";
|
||||
pathDescription.back().turn_instruction = TurnInstructions.NoTurn;
|
||||
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->name_id;
|
||||
}
|
||||
} else {
|
||||
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
|
||||
}
|
||||
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
|
||||
//TODO: this is never called actually?
|
||||
if(pathDescription.size() > 2) {
|
||||
pathDescription.erase(pathDescription.begin());
|
||||
pathDescription[0].turnInstruction = TurnInstructions.HeadOn;
|
||||
pathDescription[0].turn_instruction = TurnInstructions.HeadOn;
|
||||
pathDescription[0].necessary = true;
|
||||
start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID;
|
||||
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
|
||||
start_phantom.nodeBasedEdgeNameID = pathDescription[0].name_id;
|
||||
}
|
||||
} else {
|
||||
pathDescription[0].duration *= start_phantom.ratio;
|
||||
@ -208,11 +203,9 @@ public:
|
||||
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
|
||||
if(pathDescription[i].necessary) {
|
||||
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
|
||||
pathDescription[i].bearing = angle;
|
||||
pathDescription[i].bearing = angle*10;
|
||||
}
|
||||
}
|
||||
|
||||
// BuildRouteSummary(entireLength, duration);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -44,10 +44,10 @@ public:
|
||||
|
||||
//TODO: reorder parameters
|
||||
void Run(
|
||||
http::Reply & reply,
|
||||
const RawRouteData &rawRoute,
|
||||
PhantomNodes &phantomNodes,
|
||||
const DataFacadeT * facade
|
||||
const RawRouteData &raw_route,
|
||||
const PhantomNodes &phantom_node_list,
|
||||
DataFacadeT * facade,
|
||||
http::Reply & reply
|
||||
) {
|
||||
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content.push_back(
|
||||
@ -61,38 +61,41 @@ public:
|
||||
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||
"</metadata>");
|
||||
reply.content.push_back("<rte>");
|
||||
bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) &&
|
||||
(rawRoute.computedShortestPath.size() );
|
||||
bool found_route = (raw_route.lengthOfShortestPath != INT_MAX) &&
|
||||
(raw_route.unpacked_path_segments[0].size());
|
||||
if( found_route ) {
|
||||
convertInternalLatLonToString(
|
||||
phantomNodes.startPhantom.location.lat,
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.startPhantom.location.lat,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
convertInternalLatLonToString(
|
||||
phantomNodes.startPhantom.location.lon,
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.startPhantom.location.lon,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
|
||||
for(unsigned i=0; i < raw_route.unpacked_path_segments.size(); ++i){
|
||||
BOOST_FOREACH(
|
||||
const _PathData & pathData,
|
||||
rawRoute.computedShortestPath
|
||||
const PathData & pathData,
|
||||
raw_route.unpacked_path_segments[i]
|
||||
) {
|
||||
current = facade->GetCoordinateOfNode(pathData.node);
|
||||
|
||||
convertInternalLatLonToString(current.lat, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
convertInternalLatLonToString(current.lon, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(current.lon, tmp);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
}
|
||||
convertInternalLatLonToString(
|
||||
phantomNodes.targetPhantom.location.lat,
|
||||
}
|
||||
// Add the via point or the end coordinate
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.targetPhantom.location.lat,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
|
||||
convertInternalLatLonToString(
|
||||
phantomNodes.targetPhantom.location.lon,
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.targetPhantom.location.lon,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
|
||||
|
@ -44,9 +44,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
template<class DataFacadeT>
|
||||
class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
|
||||
private:
|
||||
DataFacadeT * facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory;
|
||||
DescriptionFactory alternateDescriptionFactory;
|
||||
DescriptionFactory alternate_descriptionFactory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout{
|
||||
@ -68,6 +69,7 @@ private:
|
||||
int position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
||||
|
||||
struct RouteNames {
|
||||
std::string shortestPathName1;
|
||||
@ -77,37 +79,72 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
JSONDescriptor() : entered_restricted_area_count(0) {}
|
||||
JSONDescriptor() :
|
||||
facade(NULL),
|
||||
entered_restricted_area_count(0)
|
||||
{
|
||||
shortest_leg_end_indices.push_back(0);
|
||||
alternative_leg_end_indices.push_back(0);
|
||||
}
|
||||
|
||||
void SetConfig(const DescriptorConfig & c) { config = c; }
|
||||
|
||||
//TODO: reorder parameters
|
||||
void Run(
|
||||
http::Reply & reply,
|
||||
const RawRouteData & raw_route_information,
|
||||
PhantomNodes & phantom_nodes,
|
||||
const DataFacadeT * facade
|
||||
int DescribeLeg(
|
||||
const std::vector<PathData> & route_leg,
|
||||
const PhantomNodes & leg_phantoms
|
||||
) {
|
||||
int added_element_count = 0;
|
||||
//Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
BOOST_FOREACH(const PathData & path_data, route_leg) {
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data );
|
||||
++added_element_count;
|
||||
}
|
||||
// description_factory.SetEndSegment( leg_phantoms.targetPhantom );
|
||||
++added_element_count;
|
||||
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count );
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
WriteHeaderToOutput(reply.content);
|
||||
void Run(
|
||||
const RawRouteData & raw_route,
|
||||
const PhantomNodes & phantom_nodes,
|
||||
// TODO: move facade initalization to c'tor
|
||||
DataFacadeT * f,
|
||||
http::Reply & reply
|
||||
) {
|
||||
facade = f;
|
||||
reply.content.push_back(
|
||||
"{\"status\":"
|
||||
);
|
||||
|
||||
if(INT_MAX == raw_route.lengthOfShortestPath) {
|
||||
//We do not need to do much, if there is no route ;-)
|
||||
reply.content.push_back(
|
||||
"207,\"status_message\": \"Cannot find route between points\"}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if(raw_route_information.lengthOfShortestPath != INT_MAX) {
|
||||
description_factory.SetStartSegment(phantom_nodes.startPhantom);
|
||||
reply.content.push_back("0,"
|
||||
"\"status_message\": \"Found route between points\",");
|
||||
|
||||
//Get all the coordinates for the computed route
|
||||
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedShortestPath) {
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current, path_data );
|
||||
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
|
||||
for( unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i ) {
|
||||
const int added_segments = DescribeLeg(
|
||||
raw_route.unpacked_path_segments[i],
|
||||
raw_route.segmentEndCoordinates[i]
|
||||
);
|
||||
BOOST_ASSERT( 0 < added_segments );
|
||||
shortest_leg_end_indices.push_back(
|
||||
added_segments + shortest_leg_end_indices.back()
|
||||
);
|
||||
}
|
||||
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||
} else {
|
||||
//We do not need to do much, if there is no route ;-)
|
||||
reply.content.push_back("207,"
|
||||
"\"status_message\": \"Cannot find route between points\",");
|
||||
}
|
||||
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
reply.content.push_back("\"route_geometry\": ");
|
||||
if(config.geometry) {
|
||||
description_factory.AppendEncodedPolylineString(
|
||||
@ -118,30 +155,20 @@ public:
|
||||
reply.content.push_back("[]");
|
||||
}
|
||||
|
||||
reply.content.push_back(","
|
||||
"\"route_instructions\": [");
|
||||
entered_restricted_area_count = 0;
|
||||
reply.content.push_back(",\"route_instructions\": [");
|
||||
if(config.instructions) {
|
||||
BuildTextualDescription(
|
||||
description_factory,
|
||||
reply,
|
||||
raw_route_information.lengthOfShortestPath,
|
||||
raw_route.lengthOfShortestPath,
|
||||
facade,
|
||||
shortest_path_segments
|
||||
);
|
||||
} else {
|
||||
BOOST_FOREACH(
|
||||
const SegmentInformation & segment,
|
||||
description_factory.pathDescription
|
||||
) {
|
||||
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||
}
|
||||
}
|
||||
reply.content.push_back("],");
|
||||
description_factory.BuildRouteSummary(
|
||||
description_factory.entireLength,
|
||||
raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty)
|
||||
raw_route.lengthOfShortestPath
|
||||
);
|
||||
|
||||
reply.content.push_back("\"route_summary\":");
|
||||
@ -167,62 +194,67 @@ public:
|
||||
|
||||
//only one alternative route is computed at this time, so this is hardcoded
|
||||
|
||||
if(raw_route_information.lengthOfAlternativePath != INT_MAX) {
|
||||
alternateDescriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
||||
if(raw_route.lengthOfAlternativePath != INT_MAX) {
|
||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
|
||||
//Get all the coordinates for the computed route
|
||||
BOOST_FOREACH(const _PathData & path_data, raw_route_information.computedAlternativePath) {
|
||||
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) {
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternateDescriptionFactory.AppendSegment(current, path_data );
|
||||
alternate_descriptionFactory.AppendSegment(current, path_data );
|
||||
}
|
||||
alternateDescriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||
alternate_descriptionFactory.SetEndSegment(phantom_nodes.targetPhantom);
|
||||
}
|
||||
alternateDescriptionFactory.Run(facade, config.zoom_level);
|
||||
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
||||
|
||||
//give an array of alternative routes
|
||||
// //give an array of alternative routes
|
||||
reply.content.push_back("\"alternative_geometries\": [");
|
||||
if(config.geometry && INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
//Generate the linestrings for each alternative
|
||||
alternateDescriptionFactory.AppendEncodedPolylineString(
|
||||
alternate_descriptionFactory.AppendEncodedPolylineString(
|
||||
config.encode_geometry,
|
||||
reply.content
|
||||
);
|
||||
}
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"alternative_instructions\":[");
|
||||
entered_restricted_area_count = 0;
|
||||
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
reply.content.push_back("[");
|
||||
//Generate instructions for each alternative
|
||||
if(config.instructions) {
|
||||
BuildTextualDescription(
|
||||
alternateDescriptionFactory,
|
||||
alternate_descriptionFactory,
|
||||
reply,
|
||||
raw_route_information.lengthOfAlternativePath,
|
||||
raw_route.lengthOfAlternativePath,
|
||||
facade,
|
||||
alternative_path_segments
|
||||
);
|
||||
} else {
|
||||
BOOST_FOREACH(const SegmentInformation & segment, alternateDescriptionFactory.pathDescription) {
|
||||
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||
}
|
||||
}
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"alternative_summaries\":[");
|
||||
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
|
||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
//Generate route summary (length, duration) for each alternative
|
||||
alternateDescriptionFactory.BuildRouteSummary(alternateDescriptionFactory.entireLength, raw_route_information.lengthOfAlternativePath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty));
|
||||
alternate_descriptionFactory.BuildRouteSummary(
|
||||
alternate_descriptionFactory.entireLength,
|
||||
raw_route.lengthOfAlternativePath
|
||||
);
|
||||
reply.content.push_back("{");
|
||||
reply.content.push_back("\"total_distance\":");
|
||||
reply.content.push_back(alternateDescriptionFactory.summary.lengthString);
|
||||
reply.content.push_back(
|
||||
alternate_descriptionFactory.summary.lengthString
|
||||
);
|
||||
reply.content.push_back(","
|
||||
"\"total_time\":");
|
||||
reply.content.push_back(alternateDescriptionFactory.summary.durationString);
|
||||
reply.content.push_back(
|
||||
alternate_descriptionFactory.summary.durationString
|
||||
);
|
||||
reply.content.push_back(","
|
||||
"\"start_point\":\"");
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
||||
reply.content.push_back(
|
||||
facade->GetEscapedNameForNameID(
|
||||
description_factory.summary.startName
|
||||
)
|
||||
);
|
||||
reply.content.push_back("\","
|
||||
"\"end_point\":\"");
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
||||
@ -231,7 +263,7 @@ public:
|
||||
}
|
||||
reply.content.push_back("],");
|
||||
|
||||
//Get Names for both routes
|
||||
// //Get Names for both routes
|
||||
RouteNames routeNames;
|
||||
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
||||
|
||||
@ -249,47 +281,66 @@ public:
|
||||
reply.content.push_back("],");
|
||||
//list all viapoints so that the client may display it
|
||||
reply.content.push_back("\"via_points\":[");
|
||||
std::string tmp;
|
||||
if(config.geometry && INT_MAX != raw_route_information.lengthOfShortestPath) {
|
||||
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content.push_back("[");
|
||||
if(raw_route_information.segmentEndCoordinates[i].startPhantom.location.isSet())
|
||||
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates[i].startPhantom.location, tmp);
|
||||
else
|
||||
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates[i], tmp);
|
||||
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("],");
|
||||
}
|
||||
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() );
|
||||
|
||||
std::string tmp;
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
raw_route.segmentEndCoordinates.front().startPhantom.location,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back("[");
|
||||
if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet())
|
||||
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp);
|
||||
else
|
||||
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp);
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("]");
|
||||
|
||||
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
|
||||
tmp.clear();
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
nodes.targetPhantom.location,
|
||||
tmp
|
||||
);
|
||||
reply.content.push_back(",[");
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"via_indices\":[");
|
||||
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) {
|
||||
tmp.clear();
|
||||
intToString(index, tmp);
|
||||
reply.content.push_back(tmp);
|
||||
if( index != shortest_leg_end_indices.back() ) {
|
||||
reply.content.push_back(",");
|
||||
}
|
||||
}
|
||||
reply.content.push_back("],\"alternative_indices\":[");
|
||||
if(INT_MAX != raw_route.lengthOfAlternativePath) {
|
||||
reply.content.push_back("0,");
|
||||
tmp.clear();
|
||||
intToString(alternate_descriptionFactory.pathDescription.size(), tmp);
|
||||
reply.content.push_back(tmp);
|
||||
}
|
||||
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"hint_data\": {");
|
||||
reply.content.push_back("\"checksum\":");
|
||||
intToString(raw_route_information.checkSum, tmp);
|
||||
intToString(raw_route.checkSum, tmp);
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back(", \"locations\": [");
|
||||
|
||||
std::string hint;
|
||||
for(unsigned i = 0; i < raw_route_information.segmentEndCoordinates.size(); ++i) {
|
||||
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) {
|
||||
reply.content.push_back("\"");
|
||||
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates[i].startPhantom, hint);
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].startPhantom, hint);
|
||||
reply.content.push_back(hint);
|
||||
reply.content.push_back("\", ");
|
||||
}
|
||||
EncodeObjectToBase64(raw_route_information.segmentEndCoordinates.back().targetPhantom, hint);
|
||||
EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().targetPhantom, hint);
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back(hint);
|
||||
reply.content.push_back("\"]");
|
||||
reply.content.push_back("},");
|
||||
reply.content.push_back("\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"");
|
||||
reply.content.push_back("}");
|
||||
reply.content.push_back("}}");
|
||||
}
|
||||
|
||||
// construct routes names
|
||||
@ -357,14 +408,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
inline void WriteHeaderToOutput(std::vector<std::string> & output) {
|
||||
output.push_back(
|
||||
"{"
|
||||
"\"version\": 0.3,"
|
||||
"\"status\":"
|
||||
);
|
||||
}
|
||||
|
||||
//TODO: reorder parameters
|
||||
inline void BuildTextualDescription(
|
||||
DescriptionFactory & description_factory,
|
||||
@ -383,11 +426,11 @@ public:
|
||||
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
|
||||
//Fetch data from Factory and generate a string from it.
|
||||
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
|
||||
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
entered_restricted_area_count += (current_instruction != segment.turnInstruction);
|
||||
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructions.InverseAccessRestrictionFlag;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
|
||||
if(TurnInstructions.EnterRoundAbout == current_instruction) {
|
||||
roundAbout.name_id = segment.nameID;
|
||||
roundAbout.name_id = segment.name_id;
|
||||
roundAbout.start_index = prefixSumOfNecessarySegments;
|
||||
} else {
|
||||
if(0 != prefixSumOfNecessarySegments){
|
||||
@ -407,7 +450,7 @@ public:
|
||||
}
|
||||
|
||||
reply.content.push_back("\",\"");
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.nameID));
|
||||
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
||||
reply.content.push_back("\",");
|
||||
intToString(segment.length, tmpDist);
|
||||
reply.content.push_back(tmpDist);
|
||||
@ -421,15 +464,16 @@ public:
|
||||
intToString(segment.length, tmpLength);
|
||||
reply.content.push_back(tmpLength);
|
||||
reply.content.push_back("m\",\"");
|
||||
reply.content.push_back(Azimuth::Get(segment.bearing));
|
||||
double bearing_value = round(segment.bearing/10.);
|
||||
reply.content.push_back(Azimuth::Get(bearing_value));
|
||||
reply.content.push_back("\",");
|
||||
intToString(round(segment.bearing), tmpBearing);
|
||||
intToString(bearing_value, tmpBearing);
|
||||
reply.content.push_back(tmpBearing);
|
||||
reply.content.push_back("]");
|
||||
|
||||
route_segments_list.push_back(
|
||||
Segment(
|
||||
segment.nameID,
|
||||
segment.name_id,
|
||||
segment.length,
|
||||
route_segments_list.size()
|
||||
)
|
||||
@ -461,6 +505,6 @@ public:
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
|
@ -26,22 +26,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "BaseParser.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) :
|
||||
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) {
|
||||
luaState = se.getLuaStateForThreadID(0);
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
BaseParser::BaseParser(
|
||||
ExtractorCallbacks * extractor_callbacks,
|
||||
ScriptingEnvironment & scripting_environment
|
||||
) : extractor_callbacks(extractor_callbacks),
|
||||
lua_state(scripting_environment.getLuaStateForThreadID(0)),
|
||||
scripting_environment(scripting_environment),
|
||||
use_turn_restrictions(true)
|
||||
{
|
||||
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( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) {
|
||||
throw OSRMException("ERROR occured in scripting block");
|
||||
}
|
||||
if( lua_isboolean( luaState, -1) ) {
|
||||
use_turn_restrictions = lua_toboolean(luaState, -1);
|
||||
if( lua_isboolean( lua_state, -1) ) {
|
||||
use_turn_restrictions = lua_toboolean(lua_state, -1);
|
||||
}
|
||||
if( use_turn_restrictions ) {
|
||||
SimpleLogger().Write() << "Using turn restrictions";
|
||||
@ -51,14 +66,16 @@ void BaseParser::ReadUseRestrictionsSetting() {
|
||||
}
|
||||
|
||||
void BaseParser::ReadRestrictionExceptions() {
|
||||
if(lua_function_exists(luaState, "get_exceptions" )) {
|
||||
if(lua_function_exists(lua_state, "get_exceptions" )) {
|
||||
//get list of turn restriction exceptions
|
||||
luabind::call_function<void>(
|
||||
luaState,
|
||||
lua_state,
|
||||
"get_exceptions",
|
||||
boost::ref(restriction_exceptions)
|
||||
);
|
||||
SimpleLogger().Write() << "Found " << restriction_exceptions.size() << " exceptions to turn restriction";
|
||||
const unsigned exception_count = restriction_exceptions.size();
|
||||
SimpleLogger().Write() <<
|
||||
"Found " << exception_count << " exceptions to turn restrictions:";
|
||||
BOOST_FOREACH(const std::string & str, restriction_exceptions) {
|
||||
SimpleLogger().Write() << " " << str;
|
||||
}
|
||||
@ -74,20 +91,32 @@ void BaseParser::report_errors(lua_State *L, const int status) const {
|
||||
}
|
||||
}
|
||||
|
||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) {
|
||||
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) );
|
||||
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* local_lua_state) {
|
||||
luabind::call_function<void>(
|
||||
local_lua_state,
|
||||
"node_function",
|
||||
boost::ref(n)
|
||||
);
|
||||
}
|
||||
|
||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) {
|
||||
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) );
|
||||
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* local_lua_state) {
|
||||
luabind::call_function<void>(
|
||||
local_lua_state,
|
||||
"way_function",
|
||||
boost::ref(w)
|
||||
);
|
||||
}
|
||||
|
||||
bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string) const {
|
||||
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]
|
||||
// a) the list of modes in the except tag of the restriction
|
||||
// (except_tag_string), eg: except=bus;bicycle
|
||||
// b) the lua profile defines a hierachy of modes,
|
||||
// eg: [access, vehicle, bicycle]
|
||||
|
||||
if( "" == except_tag_string ) {
|
||||
if( except_tag_string.empty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -95,8 +124,14 @@ bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string)
|
||||
//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) ) {
|
||||
BOOST_FOREACH(std::string& current_string, exceptions) {
|
||||
std::vector<std::string>::const_iterator string_iterator;
|
||||
string_iterator = std::find(
|
||||
restriction_exceptions.begin(),
|
||||
restriction_exceptions.end(),
|
||||
current_string
|
||||
);
|
||||
if( restriction_exceptions.end() != string_iterator ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASEPARSER_H_
|
||||
#define BASEPARSER_H_
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
@ -40,29 +35,40 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ExtractorCallbacks;
|
||||
class ScriptingEnvironment;
|
||||
struct ExtractionWay;
|
||||
struct ImportNode;
|
||||
|
||||
class BaseParser : boost::noncopyable {
|
||||
public:
|
||||
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
BaseParser(
|
||||
ExtractorCallbacks * extractor_callbacks,
|
||||
ScriptingEnvironment & scripting_environment
|
||||
);
|
||||
virtual ~BaseParser() {}
|
||||
virtual bool ReadHeader() = 0;
|
||||
virtual bool Parse() = 0;
|
||||
|
||||
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread);
|
||||
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread);
|
||||
virtual void report_errors(lua_State *L, const int status) const;
|
||||
virtual void ParseNodeInLua(ImportNode & n, lua_State* thread_lua_state);
|
||||
virtual void ParseWayInLua(ExtractionWay & n, lua_State* thread_lua_state);
|
||||
virtual void report_errors(lua_State * lua_state, const int status) const;
|
||||
|
||||
protected:
|
||||
virtual void ReadUseRestrictionsSetting();
|
||||
virtual void ReadRestrictionExceptions();
|
||||
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const;
|
||||
virtual bool ShouldIgnoreRestriction(
|
||||
const std::string & except_tag_string
|
||||
) const;
|
||||
|
||||
ExtractorCallbacks* extractor_callbacks;
|
||||
ScriptingEnvironment& scriptingEnvironment;
|
||||
lua_State* luaState;
|
||||
ExtractorCallbacks * extractor_callbacks;
|
||||
lua_State * lua_state;
|
||||
ScriptingEnvironment & scripting_environment;
|
||||
std::vector<std::string> restriction_exceptions;
|
||||
bool use_turn_restrictions;
|
||||
|
||||
};
|
||||
|
||||
#endif /* BASEPARSER_H_ */
|
||||
|
@ -26,6 +26,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <stxxl/sort>
|
||||
|
||||
ExtractionContainers::ExtractionContainers() {
|
||||
//Check if stxxl can be instantiated
|
||||
stxxl::vector<unsigned> dummy_vector;
|
||||
name_list.push_back("");
|
||||
}
|
||||
|
||||
ExtractionContainers::~ExtractionContainers() {
|
||||
used_node_id_list.clear();
|
||||
all_nodes_list.clear();
|
||||
all_edges_list.clear();
|
||||
name_list.clear();
|
||||
restrictions_list.clear();
|
||||
way_start_end_id_list.clear();
|
||||
}
|
||||
|
||||
void ExtractionContainers::PrepareData(
|
||||
const std::string & output_file_name,
|
||||
@ -304,7 +329,7 @@ void ExtractionContainers::PrepareData(
|
||||
edge_iterator->targetCoord.lat = node_iterator->lat;
|
||||
edge_iterator->targetCoord.lon = node_iterator->lon;
|
||||
|
||||
const double distance = ApproximateDistance(
|
||||
const double distance = FixedPointCoordinate::ApproximateDistance(
|
||||
edge_iterator->startCoord.lat,
|
||||
edge_iterator->startCoord.lon,
|
||||
node_iterator->lat,
|
||||
|
@ -28,17 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTIONCONTAINERS_H_
|
||||
#define EXTRACTIONCONTAINERS_H_
|
||||
|
||||
#include "InternalExtractorEdge.h"
|
||||
#include "ExtractorStructs.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/UUID.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <stxxl/sort>
|
||||
#include <stxxl/vector>
|
||||
|
||||
class ExtractionContainers {
|
||||
@ -58,20 +52,9 @@ public:
|
||||
STXXLWayIDStartEndVector way_start_end_id_list;
|
||||
const UUID uuid;
|
||||
|
||||
ExtractionContainers() {
|
||||
//Check if stxxl can be instantiated
|
||||
stxxl::vector<unsigned> dummy_vector;
|
||||
name_list.push_back("");
|
||||
}
|
||||
ExtractionContainers();
|
||||
|
||||
virtual ~ExtractionContainers() {
|
||||
used_node_id_list.clear();
|
||||
all_nodes_list.clear();
|
||||
all_edges_list.clear();
|
||||
name_list.clear();
|
||||
restrictions_list.clear();
|
||||
way_start_end_id_list.clear();
|
||||
}
|
||||
virtual ~ExtractionContainers();
|
||||
|
||||
void PrepareData(
|
||||
const std::string & output_file_name,
|
||||
|
78
Extractor/ExtractionWay.h
Normal file
78
Extractor/ExtractionWay.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXTRACTION_WAY_H
|
||||
#define EXTRACTION_WAY_H
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct ExtractionWay {
|
||||
ExtractionWay() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
inline void Clear(){
|
||||
id = UINT_MAX;
|
||||
nameID = UINT_MAX;
|
||||
path.clear();
|
||||
keyVals.clear();
|
||||
direction = ExtractionWay::notSure;
|
||||
speed = -1;
|
||||
backward_speed = -1;
|
||||
duration = -1;
|
||||
type = -1;
|
||||
access = true;
|
||||
roundabout = false;
|
||||
isAccessRestricted = false;
|
||||
ignoreInGrid = false;
|
||||
}
|
||||
|
||||
enum Directions {
|
||||
notSure = 0, oneway, bidirectional, opposite
|
||||
};
|
||||
unsigned id;
|
||||
unsigned nameID;
|
||||
double speed;
|
||||
double backward_speed;
|
||||
double duration;
|
||||
Directions direction;
|
||||
std::string name;
|
||||
short type;
|
||||
bool access;
|
||||
bool roundabout;
|
||||
bool isAccessRestricted;
|
||||
bool ignoreInGrid;
|
||||
std::vector< NodeID > path;
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
|
||||
#endif //EXTRACTION_WAY_H
|
@ -25,13 +25,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; }
|
||||
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) {
|
||||
externalMemory = ext;
|
||||
stringMap = strMap;
|
||||
}
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks()
|
||||
:
|
||||
stringMap(NULL),
|
||||
externalMemory(NULL)
|
||||
{ }
|
||||
|
||||
ExtractorCallbacks::ExtractorCallbacks(
|
||||
ExtractionContainers * ext,
|
||||
StringMap * strMap
|
||||
) :
|
||||
stringMap(strMap),
|
||||
externalMemory(ext)
|
||||
{ }
|
||||
|
||||
ExtractorCallbacks::~ExtractorCallbacks() { }
|
||||
|
||||
@ -62,14 +87,14 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
|
||||
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
|
||||
}
|
||||
|
||||
if(std::numeric_limits<double>::epsilon() >= fabs(-1. - parsed_way.speed)){
|
||||
if(std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed)){
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"found way with bogus speed, id: " << parsed_way.id;
|
||||
return;
|
||||
}
|
||||
|
||||
//Get the unique identifier for the street name
|
||||
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name);
|
||||
const StringMap::const_iterator & string_map_iterator = stringMap->find(parsed_way.name);
|
||||
if(stringMap->end() == string_map_iterator) {
|
||||
parsed_way.nameID = externalMemory->name_list.size();
|
||||
externalMemory->name_list.push_back(parsed_way.name);
|
||||
|
@ -28,29 +28,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTORCALLBACKS_H_
|
||||
#define EXTRACTORCALLBACKS_H_
|
||||
|
||||
#include "ExtractionContainers.h"
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractorStructs.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class ExtractionContainers;
|
||||
struct ExtractionWay;
|
||||
struct InputRestrictionContainer;
|
||||
|
||||
typedef boost::unordered_map<std::string, NodeID> StringMap;
|
||||
|
||||
class ExtractorCallbacks{
|
||||
private:
|
||||
|
||||
StringMap * stringMap;
|
||||
ExtractionContainers * externalMemory;
|
||||
|
||||
ExtractorCallbacks();
|
||||
public:
|
||||
explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap);
|
||||
explicit ExtractorCallbacks(
|
||||
ExtractionContainers * ext,
|
||||
StringMap * strMap
|
||||
);
|
||||
|
||||
~ExtractorCallbacks();
|
||||
|
||||
|
@ -28,64 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef EXTRACTORSTRUCTS_H_
|
||||
#define EXTRACTORSTRUCTS_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#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/regex.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <climits>
|
||||
#include <string>
|
||||
|
||||
typedef boost::unordered_map<std::string, NodeID > StringMap;
|
||||
typedef boost::unordered_map<std::string, std::pair<int, short> > StringToIntPairMap;
|
||||
|
||||
struct ExtractionWay {
|
||||
ExtractionWay() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
inline void Clear(){
|
||||
id = UINT_MAX;
|
||||
nameID = UINT_MAX;
|
||||
path.clear();
|
||||
keyVals.clear();
|
||||
direction = ExtractionWay::notSure;
|
||||
speed = -1;
|
||||
backward_speed = -1;
|
||||
duration = -1;
|
||||
type = -1;
|
||||
access = true;
|
||||
roundabout = false;
|
||||
isAccessRestricted = false;
|
||||
ignoreInGrid = false;
|
||||
}
|
||||
|
||||
enum Directions {
|
||||
notSure = 0, oneway, bidirectional, opposite
|
||||
};
|
||||
Directions direction;
|
||||
unsigned id;
|
||||
unsigned nameID;
|
||||
std::string name;
|
||||
double speed;
|
||||
double backward_speed;
|
||||
double duration;
|
||||
short type;
|
||||
bool access;
|
||||
bool roundabout;
|
||||
bool isAccessRestricted;
|
||||
bool ignoreInGrid;
|
||||
std::vector< NodeID > path;
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
struct ExtractorRelation {
|
||||
ExtractorRelation() : type(unknown){}
|
||||
enum {
|
||||
@ -94,49 +42,34 @@ struct ExtractorRelation {
|
||||
HashTable<std::string, std::string> keyVals;
|
||||
};
|
||||
|
||||
struct InternalExtractorEdge {
|
||||
InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(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) { }
|
||||
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) { }
|
||||
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);
|
||||
}
|
||||
NodeID start;
|
||||
NodeID target;
|
||||
short type;
|
||||
short direction;
|
||||
double speed;
|
||||
unsigned nameID;
|
||||
bool isRoundabout;
|
||||
bool ignoreInGrid;
|
||||
bool isDurationSet;
|
||||
bool isAccessRestricted;
|
||||
bool isContraFlow;
|
||||
|
||||
FixedPointCoordinate startCoord;
|
||||
FixedPointCoordinate targetCoord;
|
||||
|
||||
static InternalExtractorEdge min_value() {
|
||||
return InternalExtractorEdge(0,0);
|
||||
}
|
||||
static InternalExtractorEdge max_value() {
|
||||
return InternalExtractorEdge((std::numeric_limits<unsigned>::max)(), (std::numeric_limits<unsigned>::max)());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct _WayIDStartAndEndEdge {
|
||||
unsigned wayID;
|
||||
NodeID firstStart;
|
||||
NodeID firstTarget;
|
||||
NodeID lastStart;
|
||||
NodeID lastTarget;
|
||||
_WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {}
|
||||
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {}
|
||||
_WayIDStartAndEndEdge()
|
||||
:
|
||||
wayID(UINT_MAX),
|
||||
firstStart(UINT_MAX),
|
||||
firstTarget(UINT_MAX),
|
||||
lastStart(UINT_MAX),
|
||||
lastTarget(UINT_MAX)
|
||||
{ }
|
||||
|
||||
explicit _WayIDStartAndEndEdge(
|
||||
unsigned w,
|
||||
NodeID fs,
|
||||
NodeID ft,
|
||||
NodeID ls,
|
||||
NodeID lt
|
||||
) :
|
||||
wayID(w),
|
||||
firstStart(fs),
|
||||
firstTarget(ft),
|
||||
lastStart(ls),
|
||||
lastTarget(lt)
|
||||
{ }
|
||||
|
||||
static _WayIDStartAndEndEdge min_value() {
|
||||
return _WayIDStartAndEndEdge((std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)(), (std::numeric_limits<unsigned>::min)());
|
||||
@ -146,9 +79,12 @@ struct _WayIDStartAndEndEdge {
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
|
||||
struct CmpWayByID {
|
||||
typedef _WayIDStartAndEndEdge value_type;
|
||||
bool operator () (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
|
||||
bool operator ()(
|
||||
const _WayIDStartAndEndEdge & a,
|
||||
const _WayIDStartAndEndEdge & b
|
||||
) const {
|
||||
return a.wayID < b.wayID;
|
||||
}
|
||||
value_type max_value() {
|
||||
@ -159,9 +95,12 @@ struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDSta
|
||||
}
|
||||
};
|
||||
|
||||
struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
||||
struct Cmp {
|
||||
typedef NodeID value_type;
|
||||
bool operator () (const NodeID a, const NodeID b) const {
|
||||
bool operator ()(
|
||||
const NodeID a,
|
||||
const NodeID b
|
||||
) const {
|
||||
return a < b;
|
||||
}
|
||||
value_type max_value() {
|
||||
@ -172,7 +111,7 @@ struct Cmp : public std::binary_function<NodeID, NodeID, bool> {
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpNodeByID : public std::binary_function<ExternalMemoryNode, ExternalMemoryNode, bool> {
|
||||
struct CmpNodeByID {
|
||||
typedef ExternalMemoryNode value_type;
|
||||
bool operator () (
|
||||
const ExternalMemoryNode & a,
|
||||
@ -188,44 +127,4 @@ struct CmpNodeByID : public std::binary_function<ExternalMemoryNode, ExternalMem
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpEdgeByStartID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
|
||||
return a.start < b.start;
|
||||
}
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpEdgeByTargetID : public std::binary_function<InternalExtractorEdge, InternalExtractorEdge, bool> {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const {
|
||||
return a.target < b.target;
|
||||
}
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string GetRandomString() {
|
||||
char s[128];
|
||||
static const char alphanum[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
for (int i = 0; i < 127; ++i) {
|
||||
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||
}
|
||||
s[127] = 0;
|
||||
return std::string(s);
|
||||
}
|
||||
|
||||
#endif /* EXTRACTORSTRUCTS_H_ */
|
||||
|
207
Extractor/InternalExtractorEdge.h
Normal file
207
Extractor/InternalExtractorEdge.h
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef INTERNAL_EXTRACTOR_EDGE_H
|
||||
#define INTERNAL_EXTRACTOR_EDGE_H
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
struct InternalExtractorEdge {
|
||||
InternalExtractorEdge()
|
||||
:
|
||||
start(0),
|
||||
target(0),
|
||||
type(0),
|
||||
direction(0),
|
||||
speed(0),
|
||||
nameID(0),
|
||||
isRoundabout(false),
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false)
|
||||
{ }
|
||||
|
||||
explicit InternalExtractorEdge(NodeID start, NodeID target)
|
||||
:
|
||||
start(start),
|
||||
target(target),
|
||||
type(0),
|
||||
direction(0),
|
||||
speed(0),
|
||||
nameID(0),
|
||||
isRoundabout(false),
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false)
|
||||
{ }
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
NodeID target,
|
||||
short type,
|
||||
short d,
|
||||
double speed
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
type(type),
|
||||
direction(d),
|
||||
speed(speed),
|
||||
nameID(0),
|
||||
isRoundabout(false),
|
||||
ignoreInGrid(false),
|
||||
isDurationSet(false),
|
||||
isAccessRestricted(false),
|
||||
isContraFlow(false)
|
||||
{ }
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
NodeID target,
|
||||
short type,
|
||||
short direction,
|
||||
double speed,
|
||||
unsigned nameID,
|
||||
bool isRoundabout,
|
||||
bool ignoreInGrid,
|
||||
bool isDurationSet,
|
||||
bool isAccressRestricted
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
type(type),
|
||||
direction(direction),
|
||||
speed(speed),
|
||||
nameID(nameID),
|
||||
isRoundabout(isRoundabout),
|
||||
ignoreInGrid(ignoreInGrid),
|
||||
isDurationSet(isDurationSet),
|
||||
isAccessRestricted(isAccressRestricted),
|
||||
isContraFlow(false)
|
||||
{
|
||||
BOOST_ASSERT(0 <= type);
|
||||
}
|
||||
|
||||
explicit InternalExtractorEdge(
|
||||
NodeID start,
|
||||
NodeID target,
|
||||
short type,
|
||||
short direction,
|
||||
double speed,
|
||||
unsigned nameID,
|
||||
bool isRoundabout,
|
||||
bool ignoreInGrid,
|
||||
bool isDurationSet,
|
||||
bool isAccressRestricted,
|
||||
bool isContraFlow
|
||||
) :
|
||||
start(start),
|
||||
target(target),
|
||||
type(type),
|
||||
direction(direction),
|
||||
speed(speed),
|
||||
nameID(nameID),
|
||||
isRoundabout(isRoundabout),
|
||||
ignoreInGrid(ignoreInGrid),
|
||||
isDurationSet(isDurationSet),
|
||||
isAccessRestricted(isAccressRestricted),
|
||||
isContraFlow(isContraFlow)
|
||||
{
|
||||
BOOST_ASSERT(0 <= type);
|
||||
}
|
||||
|
||||
// necessary static util functions for stxxl's sorting
|
||||
static InternalExtractorEdge min_value() {
|
||||
return InternalExtractorEdge(0,0);
|
||||
}
|
||||
static InternalExtractorEdge max_value() {
|
||||
return InternalExtractorEdge(
|
||||
std::numeric_limits<unsigned>::max(),
|
||||
std::numeric_limits<unsigned>::max()
|
||||
);
|
||||
}
|
||||
|
||||
NodeID start;
|
||||
NodeID target;
|
||||
short type;
|
||||
short direction;
|
||||
double speed;
|
||||
unsigned nameID;
|
||||
bool isRoundabout;
|
||||
bool ignoreInGrid;
|
||||
bool isDurationSet;
|
||||
bool isAccessRestricted;
|
||||
bool isContraFlow;
|
||||
|
||||
FixedPointCoordinate startCoord;
|
||||
FixedPointCoordinate targetCoord;
|
||||
};
|
||||
|
||||
struct CmpEdgeByStartID {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
bool operator ()(
|
||||
const InternalExtractorEdge & a,
|
||||
const InternalExtractorEdge & b
|
||||
) const {
|
||||
return a.start < b.start;
|
||||
}
|
||||
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
struct CmpEdgeByTargetID {
|
||||
typedef InternalExtractorEdge value_type;
|
||||
|
||||
bool operator ()(
|
||||
const InternalExtractorEdge & a,
|
||||
const InternalExtractorEdge & b
|
||||
) const {
|
||||
return a.target < b.target;
|
||||
}
|
||||
|
||||
value_type max_value() {
|
||||
return InternalExtractorEdge::max_value();
|
||||
}
|
||||
|
||||
value_type min_value() {
|
||||
return InternalExtractorEdge::min_value();
|
||||
}
|
||||
};
|
||||
|
||||
#endif //INTERNAL_EXTRACTOR_EDGE_H
|
@ -27,21 +27,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "PBFParser.h"
|
||||
|
||||
PBFParser::PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser( ec, se ) {
|
||||
#include "ExtractionWay.h"
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/MachineInfo.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
PBFParser::PBFParser(
|
||||
const char * fileName,
|
||||
ExtractorCallbacks * extractor_callbacks,
|
||||
ScriptingEnvironment& scripting_environment
|
||||
) : BaseParser( extractor_callbacks, scripting_environment ) {
|
||||
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. */
|
||||
|
||||
// Max 2500 items in queue, hardcoded.
|
||||
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 );
|
||||
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() {
|
||||
@ -50,18 +74,17 @@ PBFParser::~PBFParser() {
|
||||
}
|
||||
|
||||
// Clean up any leftover ThreadData objects in the queue
|
||||
_ThreadData* td;
|
||||
while (threadDataQueue->try_pop(td)) {
|
||||
delete td;
|
||||
_ThreadData* thread_data;
|
||||
while (threadDataQueue->try_pop(thread_data))
|
||||
{
|
||||
delete thread_data;
|
||||
}
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
|
||||
#ifndef NDEBUG
|
||||
SimpleLogger().Write(logDEBUG) <<
|
||||
"parsed " << blockCount <<
|
||||
" blocks from pbf with " << groupCount <<
|
||||
" groups";
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool PBFParser::ReadHeader() {
|
||||
@ -194,12 +217,15 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||
|
||||
#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()) );
|
||||
ImportNode & import_node = extracted_nodes_vector[i];
|
||||
ParseNodeInLua(
|
||||
import_node,
|
||||
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const ImportNode &n, extracted_nodes_vector) {
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector) {
|
||||
extractor_callbacks->nodeFunction(import_node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,12 +258,12 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ("restriction" == key) {
|
||||
if(val.find("only_") == 0) {
|
||||
if ( ("restriction" == key) && (val.find("only_") == 0) )
|
||||
{
|
||||
isOnlyRestriction = true;
|
||||
}
|
||||
}
|
||||
if ("except" == key) {
|
||||
if ("except" == key)
|
||||
{
|
||||
except_tag_string = val;
|
||||
}
|
||||
}
|
||||
@ -326,18 +352,23 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
|
||||
|
||||
#pragma omp parallel for schedule ( guided )
|
||||
for(int i = 0; i < number_of_ways; ++i) {
|
||||
ExtractionWay & w = parsed_way_vector[i];
|
||||
if(2 > w.path.size()) {
|
||||
ExtractionWay & extraction_way = parsed_way_vector[i];
|
||||
if (2 > extraction_way.path.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID( omp_get_thread_num()) );
|
||||
ParseWayInLua(
|
||||
extraction_way,
|
||||
scripting_environment.getLuaStateForThreadID( omp_get_thread_num())
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
|
||||
if(2 > w.path.size()) {
|
||||
BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector) {
|
||||
if (2 > extraction_way.path.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
extractor_callbacks->wayFunction(w);
|
||||
extractor_callbacks->wayFunction(extraction_way);
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,9 +396,7 @@ inline void PBFParser::loadGroup(_ThreadData * threadData) {
|
||||
}
|
||||
|
||||
inline void PBFParser::loadBlock(_ThreadData * threadData) {
|
||||
#ifndef NDEBUG
|
||||
++blockCount;
|
||||
#endif
|
||||
threadData->currentGroupID = 0;
|
||||
threadData->currentEntityID = 0;
|
||||
}
|
||||
|
@ -29,24 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define PBFPARSER_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/ref.hpp>
|
||||
|
||||
#include <osmpbf/fileformat.pb.h>
|
||||
#include <osmpbf/osmformat.pb.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include <fstream>
|
||||
|
||||
class PBFParser : public BaseParser {
|
||||
|
||||
@ -73,7 +63,11 @@ class PBFParser : public BaseParser {
|
||||
};
|
||||
|
||||
public:
|
||||
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
PBFParser(
|
||||
const char * fileName,
|
||||
ExtractorCallbacks* ec,
|
||||
ScriptingEnvironment& se
|
||||
);
|
||||
virtual ~PBFParser();
|
||||
|
||||
inline bool ReadHeader();
|
||||
@ -99,11 +93,8 @@ private:
|
||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/* counting the number of read blocks and groups */
|
||||
unsigned groupCount;
|
||||
unsigned blockCount;
|
||||
#endif
|
||||
|
||||
std::fstream input; // the input stream to parse
|
||||
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
|
||||
|
@ -27,6 +27,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "ScriptingEnvironment.h"
|
||||
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../Util/LuaUtil.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
ScriptingEnvironment::ScriptingEnvironment() {}
|
||||
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
|
||||
SimpleLogger().Write() << "Using script " << fileName;
|
||||
|
@ -28,17 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SCRIPTINGENVIRONMENT_H_
|
||||
#define SCRIPTINGENVIRONMENT_H_
|
||||
|
||||
#include "ExtractionHelperFunctions.h"
|
||||
#include "ExtractorStructs.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>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
class ScriptingEnvironment {
|
||||
public:
|
||||
ScriptingEnvironment();
|
||||
|
@ -27,16 +27,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "XMLParser.h"
|
||||
|
||||
#include "ExtractorStructs.h"
|
||||
#include "ExtractionWay.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/ImportNode.h"
|
||||
#include "../DataStructures/InputReaderFactory.h"
|
||||
#include "../DataStructures/Restriction.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.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);
|
||||
}
|
||||
|
||||
@ -59,7 +63,7 @@ bool XMLParser::Parse() {
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
|
||||
ImportNode n = _ReadXMLNode();
|
||||
ParseNodeInLua( n, luaState );
|
||||
ParseNodeInLua( n, lua_state );
|
||||
extractor_callbacks->nodeFunction(n);
|
||||
// if(!extractor_callbacks->nodeFunction(n))
|
||||
// std::cerr << "[XMLParser] dense node not parsed" << std::endl;
|
||||
@ -67,7 +71,7 @@ bool XMLParser::Parse() {
|
||||
|
||||
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
|
||||
ExtractionWay way = _ReadXMLWay( );
|
||||
ParseWayInLua( way, luaState );
|
||||
ParseWayInLua( way, lua_state );
|
||||
extractor_callbacks->wayFunction(way);
|
||||
// if(!extractor_callbacks->wayFunction(way))
|
||||
// std::cerr << "[PBFParser] way not parsed" << std::endl;
|
||||
|
@ -28,18 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef XMLPARSER_H_
|
||||
#define XMLPARSER_H_
|
||||
|
||||
#include "ExtractorCallbacks.h"
|
||||
#include "BaseParser.h"
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
|
||||
class XMLParser : public BaseParser {
|
||||
public:
|
||||
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se);
|
||||
XMLParser(
|
||||
const char* filename,
|
||||
ExtractorCallbacks* ec,
|
||||
ScriptingEnvironment& se
|
||||
);
|
||||
bool ReadHeader();
|
||||
bool Parse();
|
||||
|
||||
|
84
Include/osrm/Coordinate.h
Normal file
84
Include/osrm/Coordinate.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static const double COORDINATE_PRECISION = 1000000.;
|
||||
|
||||
struct FixedPointCoordinate {
|
||||
int lat;
|
||||
int lon;
|
||||
|
||||
FixedPointCoordinate();
|
||||
explicit FixedPointCoordinate (int lat, int lon);
|
||||
void Reset();
|
||||
bool isSet() const;
|
||||
bool isValid() const;
|
||||
bool operator==(const FixedPointCoordinate & other) const;
|
||||
|
||||
static double ApproximateDistance(
|
||||
const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2
|
||||
);
|
||||
|
||||
static double ApproximateDistance(
|
||||
const FixedPointCoordinate & c1,
|
||||
const FixedPointCoordinate & c2
|
||||
);
|
||||
|
||||
static double ApproximateEuclideanDistance(
|
||||
const FixedPointCoordinate & c1,
|
||||
const FixedPointCoordinate & c2
|
||||
);
|
||||
|
||||
static void convertInternalLatLonToString(
|
||||
const int value,
|
||||
std::string & output
|
||||
);
|
||||
|
||||
static void convertInternalCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
);
|
||||
|
||||
static void convertInternalReversedCoordinateToString(
|
||||
const FixedPointCoordinate & coord,
|
||||
std::string & output
|
||||
);
|
||||
};
|
||||
|
||||
inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){
|
||||
out << "(" << c.lat << "," << c.lon << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
@ -43,4 +43,3 @@ namespace http {
|
||||
}
|
||||
|
||||
#endif //HTTP_HEADER_H
|
||||
|
@ -29,10 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define REPLY_H
|
||||
|
||||
#include "Header.h"
|
||||
#include "../../Util/StringUtil.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -48,7 +46,7 @@ const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
|
||||
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
|
||||
|
||||
class Reply {
|
||||
public:
|
||||
public:
|
||||
enum status_type {
|
||||
ok = 200,
|
||||
badRequest = 400,
|
||||
@ -62,8 +60,10 @@ class Reply {
|
||||
std::vector<std::string> content;
|
||||
static Reply StockReply(status_type status);
|
||||
void setSize(const unsigned size);
|
||||
void SetUncompressedSize();
|
||||
|
||||
Reply();
|
||||
private:
|
||||
private:
|
||||
static std::string ToString(Reply::status_type status);
|
||||
boost::asio::const_buffer ToBuffer(Reply::status_type status);
|
||||
};
|
@ -28,8 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ROUTE_PARAMETERS_H
|
||||
#define ROUTE_PARAMETERS_H
|
||||
|
||||
#include "../../DataStructures/Coordinate.h"
|
||||
#include "../../DataStructures/HashTable.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/fusion/container/vector.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||
@ -46,7 +45,9 @@ struct RouteParameters {
|
||||
geometry(true),
|
||||
compression(true),
|
||||
deprecatedAPI(false),
|
||||
checkSum(-1) {}
|
||||
checkSum(-1)
|
||||
{ }
|
||||
|
||||
short zoomLevel;
|
||||
bool printInstructions;
|
||||
bool alternateRoute;
|
||||
@ -60,10 +61,9 @@ struct RouteParameters {
|
||||
std::string language;
|
||||
std::vector<std::string> hints;
|
||||
std::vector<FixedPointCoordinate> coordinates;
|
||||
typedef HashTable<std::string, std::string>::const_iterator OptionsIterator;
|
||||
|
||||
void setZoomLevel(const short i) {
|
||||
if (18 > i && 0 < i) {
|
||||
if (18 >= i && 0 <= i) {
|
||||
zoomLevel = i;
|
||||
}
|
||||
}
|
||||
@ -97,9 +97,11 @@ struct RouteParameters {
|
||||
}
|
||||
|
||||
void addHint(const std::string & s) {
|
||||
hints.resize(coordinates.size());
|
||||
hints.resize( coordinates.size() );
|
||||
if( !hints.empty() ) {
|
||||
hints.back() = s;
|
||||
}
|
||||
}
|
||||
|
||||
void setLanguage(const std::string & s) {
|
||||
language = s;
|
@ -24,12 +24,15 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
#include <cstdlib>
|
||||
|
||||
int main( int argc, char* argv[] ) {
|
||||
size_t size = sizeof(void*);
|
||||
if ( 4 == size ) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#ifndef SERVER_PATH_H
|
||||
#define SERVER_PATH_H
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef boost::unordered_map<const std::string, boost::filesystem::path> ServerPaths;
|
||||
|
||||
#endif //SERVER_PATH_H
|
@ -28,38 +28,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef OSRM_H
|
||||
#define OSRM_H
|
||||
|
||||
#include "OSRM.h"
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include "../Plugins/BasePlugin.h"
|
||||
#include "../Plugins/HelloWorldPlugin.h"
|
||||
#include "../Plugins/LocatePlugin.h"
|
||||
#include "../Plugins/NearestPlugin.h"
|
||||
#include "../Plugins/TimestampPlugin.h"
|
||||
#include "../Plugins/ViaRoutePlugin.h"
|
||||
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||
#include "../Server/DataStructures/SharedBarriers.h"
|
||||
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||
#include "../Server/DataStructures/RouteParameters.h"
|
||||
#include "../Util/InputFileUtil.h"
|
||||
#include "../Util/OSRMException.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
class OSRM_impl;
|
||||
|
||||
#include <vector>
|
||||
|
||||
class OSRM : boost::noncopyable {
|
||||
class OSRM {
|
||||
private:
|
||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||
OSRM_impl * OSRM_pimpl_;
|
||||
public:
|
||||
OSRM(
|
||||
const ServerPaths & paths,
|
||||
@ -67,14 +46,6 @@ public:
|
||||
);
|
||||
~OSRM();
|
||||
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||
|
||||
private:
|
||||
void RegisterPlugin(BasePlugin * plugin);
|
||||
PluginMap plugin_map;
|
||||
bool use_shared_memory;
|
||||
SharedBarriers barrier;
|
||||
//base class pointer to the objects
|
||||
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
|
||||
};
|
||||
|
||||
#endif //OSRM_H
|
||||
#endif // OSRM_H
|
||||
|
@ -26,17 +26,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "OSRM.h"
|
||||
#include "OSRM_impl.h"
|
||||
|
||||
OSRM::OSRM( const ServerPaths & server_paths, const bool use_shared_memory )
|
||||
#include "../Plugins/HelloWorldPlugin.h"
|
||||
#include "../Plugins/LocatePlugin.h"
|
||||
#include "../Plugins/NearestPlugin.h"
|
||||
#include "../Plugins/TimestampPlugin.h"
|
||||
#include "../Plugins/ViaRoutePlugin.h"
|
||||
|
||||
#include "../Server/DataStructures/BaseDataFacade.h"
|
||||
#include "../Server/DataStructures/InternalDataFacade.h"
|
||||
#include "../Server/DataStructures/SharedBarriers.h"
|
||||
#include "../Server/DataStructures/SharedDataFacade.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
OSRM_impl::OSRM_impl( const ServerPaths & server_paths, const bool use_shared_memory )
|
||||
:
|
||||
use_shared_memory(use_shared_memory)
|
||||
{
|
||||
if( !use_shared_memory ) {
|
||||
if (use_shared_memory)
|
||||
{
|
||||
barrier = new SharedBarriers();
|
||||
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
|
||||
}
|
||||
else
|
||||
{
|
||||
query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
|
||||
server_paths
|
||||
);
|
||||
} else {
|
||||
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
|
||||
}
|
||||
|
||||
//The following plugins handle all requests.
|
||||
@ -65,13 +83,16 @@ OSRM::OSRM( const ServerPaths & server_paths, const bool use_shared_memory )
|
||||
);
|
||||
}
|
||||
|
||||
OSRM::~OSRM() {
|
||||
OSRM_impl::~OSRM_impl() {
|
||||
BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
|
||||
delete plugin_pointer.second;
|
||||
}
|
||||
if( use_shared_memory ) {
|
||||
delete barrier;
|
||||
}
|
||||
}
|
||||
|
||||
void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
||||
void OSRM_impl::RegisterPlugin(BasePlugin * plugin) {
|
||||
SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
|
||||
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
|
||||
delete plugin_map.find(plugin->GetDescriptor())->second;
|
||||
@ -79,7 +100,7 @@ void OSRM::RegisterPlugin(BasePlugin * plugin) {
|
||||
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
||||
}
|
||||
|
||||
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
void OSRM_impl::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
const PluginMap::const_iterator & iter = plugin_map.find(
|
||||
route_parameters.service
|
||||
);
|
||||
@ -90,18 +111,18 @@ void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
// lock update pending
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
> pending_lock(barrier.pending_update_mutex);
|
||||
> pending_lock(barrier->pending_update_mutex);
|
||||
|
||||
// lock query
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
> query_lock(barrier.query_mutex);
|
||||
> query_lock(barrier->query_mutex);
|
||||
|
||||
// unlock update pending
|
||||
pending_lock.unlock();
|
||||
|
||||
// increment query count
|
||||
++(barrier.number_of_queries);
|
||||
++(barrier->number_of_queries);
|
||||
|
||||
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
|
||||
}
|
||||
@ -111,21 +132,36 @@ void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
// lock query
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
> query_lock(barrier.query_mutex);
|
||||
> query_lock(barrier->query_mutex);
|
||||
|
||||
// decrement query count
|
||||
--(barrier.number_of_queries);
|
||||
--(barrier->number_of_queries);
|
||||
BOOST_ASSERT_MSG(
|
||||
0 <= barrier.number_of_queries,
|
||||
0 <= barrier->number_of_queries,
|
||||
"invalid number of queries"
|
||||
);
|
||||
|
||||
// notify all processes that were waiting for this condition
|
||||
if (0 == barrier.number_of_queries) {
|
||||
barrier.no_running_queries_condition.notify_all();
|
||||
if (0 == barrier->number_of_queries) {
|
||||
barrier->no_running_queries_condition.notify_all();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
}
|
||||
}
|
||||
|
||||
// proxy code for compilation firewall
|
||||
|
||||
OSRM::OSRM(
|
||||
const ServerPaths & paths,
|
||||
const bool use_shared_memory
|
||||
) : OSRM_pimpl_(new OSRM_impl(paths, use_shared_memory)) { }
|
||||
|
||||
OSRM::~OSRM() {
|
||||
delete OSRM_pimpl_;
|
||||
}
|
||||
|
||||
void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
|
||||
OSRM_pimpl_->RunQuery(route_parameters, reply);
|
||||
}
|
65
Library/OSRM_impl.h
Normal file
65
Library/OSRM_impl.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef OSRM_IMPL_H
|
||||
#define OSRM_IMPL_H
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../Plugins/BasePlugin.h"
|
||||
#include "../Util/ProgramOptions.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
struct SharedBarriers;
|
||||
template<class EdgeDataT>
|
||||
class BaseDataFacade;
|
||||
|
||||
class OSRM_impl : boost::noncopyable {
|
||||
private:
|
||||
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap;
|
||||
public:
|
||||
OSRM_impl(
|
||||
const ServerPaths & paths,
|
||||
const bool use_shared_memory
|
||||
);
|
||||
virtual ~OSRM_impl();
|
||||
void RunQuery(RouteParameters & route_parameters, http::Reply & reply);
|
||||
|
||||
private:
|
||||
void RegisterPlugin(BasePlugin * plugin);
|
||||
PluginMap plugin_map;
|
||||
bool use_shared_memory;
|
||||
SharedBarriers * barrier;
|
||||
//base class pointer to the objects
|
||||
BaseDataFacade<QueryEdge::EdgeData> * query_data_facade;
|
||||
};
|
||||
|
||||
#endif //OSRM_IMPL_H
|
@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASEPLUGIN_H_
|
||||
#define BASEPLUGIN_H_
|
||||
|
||||
#include "../DataStructures/Coordinate.h"
|
||||
#include "../Server/DataStructures/RouteParameters.h"
|
||||
#include "../Server/Http/Reply.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -68,7 +68,6 @@ public:
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.push_back ("{");
|
||||
reply.content.push_back ("\"version\":0.3,");
|
||||
if(
|
||||
!facade->LocateClosestEndPointForCoordinate(
|
||||
routeParameters.coordinates[0],
|
||||
@ -82,15 +81,14 @@ public:
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.push_back ("\"status\":0,");
|
||||
reply.content.push_back ("\"mapped_coordinate\":");
|
||||
convertInternalLatLonToString(result.lat, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
|
||||
reply.content.push_back("[");
|
||||
reply.content.push_back(tmp);
|
||||
convertInternalLatLonToString(result.lon, tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
|
||||
reply.content.push_back(",");
|
||||
reply.content.push_back(tmp);
|
||||
reply.content.push_back("]");
|
||||
}
|
||||
reply.content.push_back(",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"");
|
||||
reply.content.push_back("}");
|
||||
reply.headers.resize(3);
|
||||
if(!routeParameters.jsonpParameter.empty()) {
|
||||
|
@ -25,13 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NearestPlugin_H_
|
||||
#define NearestPlugin_H_
|
||||
#ifndef NEAREST_PLUGIN_H
|
||||
#define NEAREST_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
/*
|
||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||
*/
|
||||
@ -44,11 +46,15 @@ public:
|
||||
facade(facade),
|
||||
descriptor_string("nearest")
|
||||
{
|
||||
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor
|
||||
descriptorTable.insert(std::make_pair("json", 1));
|
||||
descriptorTable.emplace("", 0); //default descriptor
|
||||
descriptorTable.emplace("json", 1);
|
||||
}
|
||||
const std::string & GetDescriptor() const { return descriptor_string; }
|
||||
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
|
||||
|
||||
void HandleRequest(
|
||||
const RouteParameters & routeParameters,
|
||||
http::Reply& reply
|
||||
) {
|
||||
//check number of parameters
|
||||
if(!routeParameters.coordinates.size()) {
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
@ -75,32 +81,26 @@ public:
|
||||
}
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.push_back("{");
|
||||
reply.content.push_back("\"version\":0.3,");
|
||||
reply.content.push_back("\"status\":");
|
||||
reply.content.push_back("{\"status\":");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
reply.content.push_back("0,");
|
||||
} else {
|
||||
reply.content.push_back("207,");
|
||||
}
|
||||
reply.content.push_back("\"mapped_coordinate\":");
|
||||
reply.content.push_back("[");
|
||||
reply.content.push_back("\"mapped_coordinate\":[");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
convertInternalLatLonToString(result.location.lat, temp_string);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
convertInternalLatLonToString(result.location.lon, temp_string);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
||||
reply.content.push_back(",");
|
||||
reply.content.push_back(temp_string);
|
||||
}
|
||||
reply.content.push_back("],");
|
||||
reply.content.push_back("\"name\":\"");
|
||||
reply.content.push_back("],\"name\":\"");
|
||||
if(UINT_MAX != result.edgeBasedNode) {
|
||||
facade->GetName(result.nodeBasedEdgeNameID, temp_string);
|
||||
reply.content.push_back(temp_string);
|
||||
}
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"");
|
||||
reply.content.push_back("}");
|
||||
reply.content.push_back("\"}");
|
||||
reply.headers.resize(3);
|
||||
if( !routeParameters.jsonpParameter.empty() ) {
|
||||
reply.content.push_back(")");
|
||||
@ -125,8 +125,8 @@ public:
|
||||
|
||||
private:
|
||||
DataFacadeT * facade;
|
||||
HashTable<std::string, unsigned> descriptorTable;
|
||||
boost::unordered_map<std::string, unsigned> descriptorTable;
|
||||
std::string descriptor_string;
|
||||
};
|
||||
|
||||
#endif /* NearestPlugin_H_ */
|
||||
#endif /* NEAREST_PLUGIN_H */
|
||||
|
@ -48,13 +48,11 @@ public:
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.push_back("{");
|
||||
reply.content.push_back("\"version\":0.3,");
|
||||
reply.content.push_back("\"status\":");
|
||||
reply.content.push_back("0,");
|
||||
reply.content.push_back("\"timestamp\":\"");
|
||||
reply.content.push_back(facade->GetTimestamp());
|
||||
reply.content.push_back("\"");
|
||||
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"");
|
||||
reply.content.push_back("}");
|
||||
reply.headers.resize(3);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
|
@ -83,7 +83,7 @@ public:
|
||||
|
||||
RawRouteData rawRoute;
|
||||
rawRoute.checkSum = facade->GetCheckSum();
|
||||
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
||||
const bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
|
||||
std::vector<std::string> textCoord;
|
||||
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
|
||||
if( !checkCoord(routeParameters.coordinates[i]) ) {
|
||||
@ -110,12 +110,13 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
|
||||
}
|
||||
|
||||
if(
|
||||
( routeParameters.alternateRoute ) &&
|
||||
(1 == rawRoute.segmentEndCoordinates.size())
|
||||
@ -175,7 +176,7 @@ public:
|
||||
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
|
||||
desc->SetConfig(descriptorConfig);
|
||||
|
||||
desc->Run(reply, rawRoute, phantomNodes, facade);
|
||||
desc->Run(rawRoute, phantomNodes, facade, reply);
|
||||
if("" != routeParameters.jsonpParameter) {
|
||||
reply.content.push_back(")\n");
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "BasicRoutingInterface.h"
|
||||
#include "../DataStructures/SearchEngineData.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
@ -77,7 +78,8 @@ public:
|
||||
|
||||
void operator()(
|
||||
const PhantomNodes & phantom_node_pair,
|
||||
RawRouteData & raw_route_data) {
|
||||
RawRouteData & raw_route_data
|
||||
) {
|
||||
if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) ||
|
||||
phantom_node_pair.PhantomNodesHaveEqualLocation()
|
||||
) {
|
||||
@ -212,12 +214,19 @@ public:
|
||||
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
|
||||
} else {
|
||||
//sharing (s) = sharing (t)
|
||||
approximated_reverse_sharing[v] = approximated_reverse_sharing[u];
|
||||
boost::unordered_map<NodeID, int>::const_iterator rev_iterator = approximated_reverse_sharing.find(u);
|
||||
const int rev_sharing = (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
|
||||
approximated_reverse_sharing[v] = rev_sharing;
|
||||
}
|
||||
}
|
||||
std::vector<NodeID> nodes_that_passed_preselection;
|
||||
BOOST_FOREACH(const NodeID node, via_node_candidate_list) {
|
||||
int approximated_sharing = approximated_forward_sharing[node] + approximated_reverse_sharing[node];
|
||||
boost::unordered_map<NodeID, int>::const_iterator fwd_iterator = approximated_forward_sharing.find(node);
|
||||
const int fwd_sharing = (fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0;
|
||||
boost::unordered_map<NodeID, int>::const_iterator rev_iterator = approximated_reverse_sharing.find(node);
|
||||
const int rev_sharing = (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0;
|
||||
|
||||
int approximated_sharing = fwd_sharing + rev_sharing;
|
||||
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);
|
||||
@ -255,16 +264,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Unpack shortest path and alternative, if they exist
|
||||
if(INT_MAX != upper_bound_to_shortest_path_distance) {
|
||||
super::UnpackPath(packedShortestPath, raw_route_data.computedShortestPath);
|
||||
raw_route_data.unpacked_path_segments.resize(1);
|
||||
super::UnpackPath(packedShortestPath, raw_route_data.unpacked_path_segments[0]);
|
||||
raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
|
||||
} else {
|
||||
raw_route_data.lengthOfShortestPath = INT_MAX;
|
||||
}
|
||||
|
||||
if(selectedViaNode != UINT_MAX) {
|
||||
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, raw_route_data.computedAlternativePath);
|
||||
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, raw_route_data.unpacked_alternative);
|
||||
raw_route_data.lengthOfAlternativePath = lengthOfViaPath;
|
||||
} else {
|
||||
raw_route_data.lengthOfAlternativePath = INT_MAX;
|
||||
@ -274,7 +285,7 @@ public:
|
||||
private:
|
||||
//unpack <s,..,v,..,t> by exploring search spaces from v
|
||||
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)
|
||||
std::vector<NodeID> packed_s_v_path, packed_v_t_path;
|
||||
super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path);
|
||||
@ -305,19 +316,19 @@ private:
|
||||
std::vector<NodeID> partiallyUnpackedViaPath;
|
||||
|
||||
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_vPath = INT_MAX;//compute path <s,..,v> by reusing forward search from s
|
||||
newBackwardHeap.Insert(via_node, 0, via_node);
|
||||
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_vPath, 2 * offset, false);
|
||||
}
|
||||
//compute path <v,..,t> by reusing backward search from node t
|
||||
NodeID v_t_middle = UINT_MAX;
|
||||
int upperBoundFor_v_t_Path = INT_MAX;
|
||||
int upperBoundFor_v_tPath = INT_MAX;
|
||||
newForwardHeap.Insert(via_node, 0, via_node);
|
||||
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_tPath, 2 * offset, true);
|
||||
}
|
||||
*real_length_of_via_path = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
|
||||
*real_length_of_via_path = upperBoundFor_s_vPath + upperBoundFor_v_tPath;
|
||||
|
||||
if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
|
||||
return;
|
||||
@ -469,28 +480,28 @@ private:
|
||||
std::vector < NodeID > packed_v_t_path;
|
||||
|
||||
*s_v_middle = UINT_MAX;
|
||||
int upperBoundFor_s_v_Path = INT_MAX;
|
||||
int upperBoundFor_s_vPath = INT_MAX;
|
||||
//compute path <s,..,v> by reusing forward search from s
|
||||
newBackwardHeap.Insert(candidate.node, 0, candidate.node);
|
||||
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_vPath, 2*offset, false);
|
||||
}
|
||||
|
||||
if(INT_MAX == upperBoundFor_s_v_Path)
|
||||
if(INT_MAX == upperBoundFor_s_vPath)
|
||||
return false;
|
||||
|
||||
//compute path <v,..,t> by reusing backward search from t
|
||||
*v_t_middle = UINT_MAX;
|
||||
int upperBoundFor_v_t_Path = INT_MAX;
|
||||
int upperBoundFor_v_tPath = INT_MAX;
|
||||
newForwardHeap.Insert(candidate.node, 0, candidate.node);
|
||||
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_tPath, 2*offset, true);
|
||||
}
|
||||
|
||||
if(INT_MAX == upperBoundFor_v_t_Path)
|
||||
if(INT_MAX == upperBoundFor_v_tPath)
|
||||
return false;
|
||||
|
||||
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path;
|
||||
*lengthOfViaPath = upperBoundFor_s_vPath + upperBoundFor_v_tPath;
|
||||
|
||||
//retrieve packed paths
|
||||
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, *s_v_middle, packed_s_v_path);
|
||||
@ -547,7 +558,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
int lengthOfPathT_Test_Path = unpackedUntilDistance;
|
||||
int lengthOfPathT_TestPath = unpackedUntilDistance;
|
||||
unpackedUntilDistance = 0;
|
||||
//Traverse path s-->v
|
||||
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
|
||||
@ -587,7 +598,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
lengthOfPathT_Test_Path += unpackedUntilDistance;
|
||||
lengthOfPathT_TestPath += unpackedUntilDistance;
|
||||
//Run actual T-Test query and compare if distances equal.
|
||||
engine_working_data.InitializeOrClearThirdThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes()
|
||||
@ -608,7 +619,7 @@ private:
|
||||
super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
|
||||
}
|
||||
}
|
||||
return (_upperBound <= lengthOfPathT_Test_Path);
|
||||
return (_upperBound <= lengthOfPathT_TestPath);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -136,7 +136,7 @@ public:
|
||||
|
||||
inline void UnpackPath(
|
||||
const std::vector<NodeID> & packed_path,
|
||||
std::vector<_PathData> & unpacked_path
|
||||
std::vector<PathData> & unpacked_path
|
||||
) const {
|
||||
const unsigned packed_path_size = packed_path.size();
|
||||
std::stack<std::pair<NodeID, NodeID> > recursion_stack;
|
||||
@ -199,7 +199,7 @@ public:
|
||||
} else {
|
||||
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
|
||||
unpacked_path.push_back(
|
||||
_PathData(
|
||||
PathData(
|
||||
ed.id,
|
||||
facade->GetNameIndexFromEdgeID(ed.id),
|
||||
facade->GetTurnInstructionForEdgeID(ed.id),
|
||||
|
@ -29,9 +29,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define SHORTESTPATHROUTING_H_
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "BasicRoutingInterface.h"
|
||||
#include "../DataStructures/SearchEngineData.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
template<class DataFacadeT>
|
||||
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
|
||||
@ -51,7 +53,7 @@ public:
|
||||
~ShortestPathRouting() {}
|
||||
|
||||
void operator()(
|
||||
std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||
const std::vector<PhantomNodes> & phantom_nodes_vector,
|
||||
RawRouteData & raw_route_data
|
||||
) const {
|
||||
BOOST_FOREACH(
|
||||
@ -66,13 +68,12 @@ public:
|
||||
}
|
||||
int distance1 = 0;
|
||||
int distance2 = 0;
|
||||
|
||||
bool search_from_1st_node = true;
|
||||
bool search_from_2nd_node = true;
|
||||
NodeID middle1 = UINT_MAX;
|
||||
NodeID middle2 = UINT_MAX;
|
||||
std::vector<NodeID> packed_path1;
|
||||
std::vector<NodeID> packed_path2;
|
||||
std::vector<std::vector<NodeID> > packed_legs1(phantom_nodes_vector.size());
|
||||
std::vector<std::vector<NodeID> > packed_legs2(phantom_nodes_vector.size());
|
||||
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes()
|
||||
@ -89,10 +90,10 @@ public:
|
||||
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
|
||||
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
|
||||
|
||||
int current_leg = 0;
|
||||
//Get distance to next pair of target nodes.
|
||||
BOOST_FOREACH(
|
||||
const PhantomNodes & phantom_node_pair,
|
||||
phantom_nodes_vector
|
||||
const PhantomNodes & phantom_node_pair, phantom_nodes_vector
|
||||
){
|
||||
forward_heap1.Clear(); forward_heap2.Clear();
|
||||
reverse_heap1.Clear(); reverse_heap2.Clear();
|
||||
@ -109,13 +110,11 @@ public:
|
||||
distance1-phantom_node_pair.startPhantom.weight1,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode
|
||||
);
|
||||
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||
forward_heap2.Insert(
|
||||
phantom_node_pair.startPhantom.edgeBasedNode,
|
||||
distance1-phantom_node_pair.startPhantom.weight1,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode
|
||||
);
|
||||
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||
}
|
||||
if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
|
||||
forward_heap1.Insert(
|
||||
@ -123,13 +122,11 @@ public:
|
||||
distance2-phantom_node_pair.startPhantom.weight2,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||
);
|
||||
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||
forward_heap2.Insert(
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1,
|
||||
distance2-phantom_node_pair.startPhantom.weight2,
|
||||
phantom_node_pair.startPhantom.edgeBasedNode+1
|
||||
);
|
||||
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||
}
|
||||
|
||||
//insert new backward nodes into backward heap, unadjusted.
|
||||
@ -138,15 +135,14 @@ public:
|
||||
phantom_node_pair.targetPhantom.weight1,
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode
|
||||
);
|
||||
// INFO("rv1: " << phantom_node_pair.targetPhantom.edgeBasedNode << ", w;" << phantom_node_pair.targetPhantom.weight1 );
|
||||
if(phantom_node_pair.targetPhantom.isBidirected() ) {
|
||||
reverse_heap2.Insert(
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode+1,
|
||||
phantom_node_pair.targetPhantom.weight2,
|
||||
phantom_node_pair.targetPhantom.edgeBasedNode+1
|
||||
);
|
||||
// INFO("rv2: " << phantom_node_pair.targetPhantom.edgeBasedNode+1 << ", w;" << phantom_node_pair.targetPhantom.weight2 );
|
||||
}
|
||||
|
||||
const int forward_offset = super::ComputeEdgeOffset(
|
||||
phantom_node_pair.startPhantom
|
||||
);
|
||||
@ -177,6 +173,7 @@ public:
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( !reverse_heap2.Empty() ) {
|
||||
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
|
||||
if( !forward_heap2.Empty() ){
|
||||
@ -225,14 +222,18 @@ public:
|
||||
);
|
||||
|
||||
//Unpack paths if they exist
|
||||
std::vector<NodeID> temporary_packed_path1;
|
||||
std::vector<NodeID> temporary_packed_path2;
|
||||
std::vector<NodeID> temporary_packed_leg1;
|
||||
std::vector<NodeID> temporary_packed_leg2;
|
||||
|
||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() );
|
||||
BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() );
|
||||
|
||||
if(INT_MAX != local_upper_bound1) {
|
||||
super::RetrievePackedPathFromHeap(
|
||||
forward_heap1,
|
||||
reverse_heap1,
|
||||
middle1,
|
||||
temporary_packed_path1
|
||||
temporary_packed_leg1
|
||||
);
|
||||
}
|
||||
|
||||
@ -241,100 +242,123 @@ public:
|
||||
forward_heap2,
|
||||
reverse_heap2,
|
||||
middle2,
|
||||
temporary_packed_path2
|
||||
temporary_packed_leg2
|
||||
);
|
||||
}
|
||||
|
||||
//if one of the paths was not found, replace it with the other one.
|
||||
if( temporary_packed_path1.empty() ) {
|
||||
temporary_packed_path1.insert(
|
||||
temporary_packed_path1.end(),
|
||||
temporary_packed_path2.begin(),
|
||||
temporary_packed_path2.end()
|
||||
if( temporary_packed_leg1.empty() ) {
|
||||
temporary_packed_leg1.insert(
|
||||
temporary_packed_leg1.end(),
|
||||
temporary_packed_leg2.begin(),
|
||||
temporary_packed_leg2.end()
|
||||
);
|
||||
local_upper_bound1 = local_upper_bound2;
|
||||
}
|
||||
if( temporary_packed_path2.empty() ) {
|
||||
temporary_packed_path2.insert(
|
||||
temporary_packed_path2.end(),
|
||||
temporary_packed_path1.begin(),
|
||||
temporary_packed_path1.end()
|
||||
if( temporary_packed_leg2.empty() ) {
|
||||
temporary_packed_leg2.insert(
|
||||
temporary_packed_leg2.end(),
|
||||
temporary_packed_leg1.begin(),
|
||||
temporary_packed_leg1.end()
|
||||
);
|
||||
local_upper_bound2 = local_upper_bound1;
|
||||
}
|
||||
|
||||
// SimpleLogger().Write() << "fetched packed paths";
|
||||
|
||||
BOOST_ASSERT_MSG(
|
||||
!temporary_packed_path1.empty() ||
|
||||
!temporary_packed_path2.empty(),
|
||||
!temporary_packed_leg1.empty() ||
|
||||
!temporary_packed_leg2.empty(),
|
||||
"tempory packed paths empty"
|
||||
);
|
||||
|
||||
//Plug paths together, s.t. end of packed path is begin of temporary packed path
|
||||
if( !packed_path1.empty() && !packed_path2.empty() ) {
|
||||
if(
|
||||
temporary_packed_path1.front() ==
|
||||
temporary_packed_path2.front()
|
||||
BOOST_ASSERT(
|
||||
(0 == current_leg) || !packed_legs1[current_leg-1].empty()
|
||||
);
|
||||
BOOST_ASSERT(
|
||||
(0 == current_leg) || !packed_legs2[current_leg-1].empty()
|
||||
);
|
||||
|
||||
if( 0 < current_leg ) {
|
||||
const NodeID end_id_of_segment1 = packed_legs1[current_leg-1].back();
|
||||
const NodeID end_id_of_segment2 = packed_legs2[current_leg-1].back();
|
||||
BOOST_ASSERT( !temporary_packed_leg1.empty() );
|
||||
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
||||
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
||||
if( ( end_id_of_segment1 != start_id_of_leg1 ) &&
|
||||
( end_id_of_segment2 != start_id_of_leg2 )
|
||||
) {
|
||||
//both new route segments start with the same node
|
||||
//thus, one of the packedPath must go.
|
||||
BOOST_ASSERT_MSG(
|
||||
(packed_path1.size() == packed_path2.size() ) ||
|
||||
(packed_path1.back() != packed_path2.back() ),
|
||||
"packed paths must be different"
|
||||
std::swap(temporary_packed_leg1, temporary_packed_leg2);
|
||||
std::swap(local_upper_bound1, local_upper_bound2);
|
||||
}
|
||||
}
|
||||
|
||||
// remove one path if both legs end at the same segment
|
||||
if( 0 < current_leg ) {
|
||||
const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
|
||||
const NodeID start_id_of_leg2 = temporary_packed_leg2.front();
|
||||
if(
|
||||
start_id_of_leg1 == start_id_of_leg2
|
||||
) {
|
||||
const NodeID last_id_of_packed_legs1 = packed_legs1[current_leg-1].back();
|
||||
const NodeID last_id_of_packed_legs2 = packed_legs2[current_leg-1].back();
|
||||
if( start_id_of_leg1 != last_id_of_packed_legs1 ) {
|
||||
packed_legs1 = packed_legs2;
|
||||
BOOST_ASSERT(
|
||||
start_id_of_leg1 == temporary_packed_leg1.front()
|
||||
);
|
||||
} else
|
||||
if( start_id_of_leg2 != last_id_of_packed_legs2 ) {
|
||||
packed_legs2 = packed_legs1;
|
||||
BOOST_ASSERT(
|
||||
start_id_of_leg2 == temporary_packed_leg2.front()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(
|
||||
packed_legs1.size() == packed_legs2.size()
|
||||
);
|
||||
|
||||
if( packed_path1.back() == temporary_packed_path1.front()) {
|
||||
packed_path2.clear();
|
||||
packed_path2.insert(
|
||||
packed_path2.end(),
|
||||
packed_path1.begin(),
|
||||
packed_path1.end()
|
||||
packed_legs1[current_leg].insert(
|
||||
packed_legs1[current_leg].end(),
|
||||
temporary_packed_leg1.begin(),
|
||||
temporary_packed_leg1.end()
|
||||
);
|
||||
} else {
|
||||
packed_path1.clear();
|
||||
packed_path1.insert(
|
||||
packed_path1.end(),
|
||||
packed_path2.begin(),
|
||||
packed_path2.end()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
//packed paths 1 and 2 may need to switch.
|
||||
if( packed_path1.back() != temporary_packed_path1.front()) {
|
||||
packed_path1.swap(packed_path2);
|
||||
std::swap(distance1, distance2);
|
||||
}
|
||||
}
|
||||
}
|
||||
packed_path1.insert(
|
||||
packed_path1.end(),
|
||||
temporary_packed_path1.begin(),
|
||||
temporary_packed_path1.end()
|
||||
);
|
||||
packed_path2.insert(
|
||||
packed_path2.end(),
|
||||
temporary_packed_path2.begin(),
|
||||
temporary_packed_path2.end()
|
||||
BOOST_ASSERT(packed_legs1[current_leg].size() == temporary_packed_leg1.size() );
|
||||
packed_legs2[current_leg].insert(
|
||||
packed_legs2[current_leg].end(),
|
||||
temporary_packed_leg2.begin(),
|
||||
temporary_packed_leg2.end()
|
||||
);
|
||||
BOOST_ASSERT(packed_legs2[current_leg].size() == temporary_packed_leg2.size() );
|
||||
|
||||
if(
|
||||
(packed_path1.back() == packed_path2.back()) &&
|
||||
(packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
|
||||
phantom_node_pair.targetPhantom.isBidirected()
|
||||
) {
|
||||
const NodeID last_node_id = packed_path2.back();
|
||||
const NodeID last_node_id = packed_legs2[current_leg].back();
|
||||
search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
|
||||
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode);
|
||||
BOOST_ASSERT( search_from_1st_node != search_from_2nd_node );
|
||||
}
|
||||
|
||||
distance1 = local_upper_bound1;
|
||||
distance2 = local_upper_bound2;
|
||||
++current_leg;
|
||||
}
|
||||
|
||||
if( distance1 > distance2 ) {
|
||||
std::swap( packed_path1, packed_path2 );
|
||||
std::swap( packed_legs1, packed_legs2 );
|
||||
}
|
||||
raw_route_data.unpacked_path_segments.resize( packed_legs1.size() );
|
||||
for(unsigned i = 0; i < packed_legs1.size(); ++i){
|
||||
BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size() );
|
||||
super::UnpackPath(
|
||||
packed_legs1[i],
|
||||
raw_route_data.unpacked_path_segments[i]
|
||||
);
|
||||
}
|
||||
remove_consecutive_duplicates_from_vector(packed_path1);
|
||||
super::UnpackPath(packed_path1, raw_route_data.computedShortestPath);
|
||||
raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
|
||||
}
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ struct APIGrammar : qi::grammar<Iterator> {
|
||||
|
||||
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)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithDot[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
||||
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
||||
@ -55,14 +55,15 @@ struct APIGrammar : qi::grammar<Iterator> {
|
||||
|
||||
string = +(qi::char_("a-zA-Z"));
|
||||
stringwithDot = +(qi::char_("a-zA-Z0-9_.-"));
|
||||
stringwithPercent = +(qi::char_("a-zA-Z0-9_.-") | qi::char_('[') | qi::char_(']') | (qi::char_('%') >> qi::char_("0-9A-Z") >> qi::char_("0-9A-Z") ));
|
||||
}
|
||||
|
||||
qi::rule<Iterator> api_call, query;
|
||||
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint,
|
||||
stringwithDot, language, instruction, geometry,
|
||||
stringwithDot, stringwithPercent, language, instruction, geometry,
|
||||
cmp, alt_route, old_API;
|
||||
|
||||
HandlerT * handler;
|
||||
};
|
||||
|
||||
|
||||
#endif /* APIGRAMMAR_H_ */
|
||||
|
240
Server/Connection.cpp
Normal file
240
Server/Connection.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "Connection.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "RequestParser.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/iostreams/filter/gzip.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace http {
|
||||
|
||||
Connection::Connection(
|
||||
boost::asio::io_service& io_service,
|
||||
RequestHandler& handler
|
||||
) :
|
||||
strand(io_service),
|
||||
TCP_socket(io_service),
|
||||
request_handler(handler),
|
||||
request_parser(new RequestParser())
|
||||
{ }
|
||||
|
||||
Connection::~Connection() {
|
||||
delete request_parser;
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::socket& Connection::socket() {
|
||||
return TCP_socket;
|
||||
}
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void Connection::start() {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap( boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void Connection::handle_read(
|
||||
const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred
|
||||
) {
|
||||
if( !e ) {
|
||||
CompressionType compression_type(noCompression);
|
||||
boost::tribool result;
|
||||
boost::tie(result, boost::tuples::ignore) = request_parser->Parse(
|
||||
request,
|
||||
incoming_data_buffer.data(),
|
||||
incoming_data_buffer.data() + bytes_transferred,
|
||||
&compression_type
|
||||
);
|
||||
|
||||
if( result ) {
|
||||
request.endpoint = TCP_socket.remote_endpoint().address();
|
||||
request_handler.handle_request(request, reply);
|
||||
|
||||
Header compression_header;
|
||||
std::vector<char> compressed_output;
|
||||
std::vector<boost::asio::const_buffer> output_buffer;
|
||||
switch(compression_type) {
|
||||
case deflateRFC1951:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "deflate";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressBufferCollection(
|
||||
reply.content,
|
||||
compression_type,
|
||||
compressed_output
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case gzipRFC1952:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "gzip";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressBufferCollection(
|
||||
reply.content,
|
||||
compression_type,
|
||||
compressed_output
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case noCompression:
|
||||
reply.SetUncompressedSize();
|
||||
output_buffer = reply.toBuffers();
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else if (!result) {
|
||||
reply = Reply::StockReply(Reply::badRequest);
|
||||
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
reply.toBuffers(),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void Connection::handle_write(const boost::system::error_code& e) {
|
||||
if (!e) {
|
||||
// Initiate graceful connection closure.
|
||||
boost::system::error_code ignoredEC;
|
||||
TCP_socket.shutdown(
|
||||
boost::asio::ip::tcp::socket::shutdown_both,
|
||||
ignoredEC
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::compressBufferCollection(
|
||||
std::vector<std::string> uncompressed_data,
|
||||
CompressionType compression_type,
|
||||
std::vector<char> & compressed_data
|
||||
) {
|
||||
boost::iostreams::gzip_params compression_parameters;
|
||||
|
||||
compression_parameters.level = boost::iostreams::zlib::best_speed;
|
||||
if ( deflateRFC1951 == compression_type ) {
|
||||
compression_parameters.noheader = true;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( compressed_data.empty() );
|
||||
boost::iostreams::filtering_ostream compressing_stream;
|
||||
|
||||
compressing_stream.push(
|
||||
boost::iostreams::gzip_compressor(compression_parameters)
|
||||
);
|
||||
compressing_stream.push(
|
||||
boost::iostreams::back_inserter(compressed_data)
|
||||
);
|
||||
|
||||
BOOST_FOREACH( const std::string & line, uncompressed_data) {
|
||||
compressing_stream << line;
|
||||
}
|
||||
|
||||
compressing_stream.reset();
|
||||
}
|
||||
}
|
@ -29,27 +29,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define CONNECTION_H
|
||||
|
||||
#include "Http/CompressionType.h"
|
||||
#include "RequestHandler.h"
|
||||
#include "RequestParser.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/iostreams/filtering_stream.hpp>
|
||||
#include <boost/iostreams/filter/gzip.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
// #include <zlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RequestHandler;
|
||||
|
||||
namespace http {
|
||||
|
||||
class RequestParser;
|
||||
|
||||
/// Represents a single connection from a client.
|
||||
class Connection : public boost::enable_shared_from_this<Connection>,
|
||||
private boost::noncopyable {
|
||||
@ -57,262 +54,36 @@ public:
|
||||
explicit Connection(
|
||||
boost::asio::io_service& io_service,
|
||||
RequestHandler& handler
|
||||
) : strand(io_service), TCP_socket(io_service), request_handler(handler) { }
|
||||
);
|
||||
|
||||
boost::asio::ip::tcp::socket& socket() {
|
||||
return TCP_socket;
|
||||
}
|
||||
~Connection();
|
||||
|
||||
boost::asio::ip::tcp::socket& socket();
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void start() {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap( boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred)
|
||||
)
|
||||
);
|
||||
}
|
||||
void start();
|
||||
|
||||
private:
|
||||
void handle_read(
|
||||
const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred
|
||||
) {
|
||||
if( !e ) {
|
||||
CompressionType compression_type(noCompression);
|
||||
boost::tribool result;
|
||||
boost::tie(result, boost::tuples::ignore) = request_parser.Parse(
|
||||
request,
|
||||
incoming_data_buffer.data(),
|
||||
incoming_data_buffer.data() + bytes_transferred,
|
||||
&compression_type
|
||||
);
|
||||
|
||||
if( result ) {
|
||||
request.endpoint = TCP_socket.remote_endpoint().address();
|
||||
request_handler.handle_request(request, reply);
|
||||
|
||||
Header compression_header;
|
||||
std::vector<char> compressed_output;
|
||||
std::vector<boost::asio::const_buffer> output_buffer;
|
||||
switch(compression_type) {
|
||||
case deflateRFC1951:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "deflate";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressBufferCollection(
|
||||
reply.content,
|
||||
compression_type,
|
||||
compressed_output
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case gzipRFC1952:
|
||||
compression_header.name = "Content-Encoding";
|
||||
compression_header.value = "gzip";
|
||||
reply.headers.insert(
|
||||
reply.headers.begin(),
|
||||
compression_header
|
||||
);
|
||||
compressBufferCollection(
|
||||
reply.content,
|
||||
compression_type,
|
||||
compressed_output
|
||||
);
|
||||
reply.setSize(compressed_output.size());
|
||||
output_buffer = reply.HeaderstoBuffers();
|
||||
output_buffer.push_back(
|
||||
boost::asio::buffer(compressed_output)
|
||||
);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
output_buffer,
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
case noCompression:
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
reply.toBuffers(),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else if (!result) {
|
||||
reply = Reply::StockReply(Reply::badRequest);
|
||||
boost::asio::async_write(
|
||||
TCP_socket,
|
||||
reply.toBuffers(),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_write,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
TCP_socket.async_read_some(
|
||||
boost::asio::buffer(incoming_data_buffer),
|
||||
strand.wrap(
|
||||
boost::bind(
|
||||
&Connection::handle_read,
|
||||
this->shared_from_this(),
|
||||
boost::asio::placeholders::error,
|
||||
boost::asio::placeholders::bytes_transferred
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void handle_write(const boost::system::error_code& e) {
|
||||
if (!e) {
|
||||
// Initiate graceful connection closure.
|
||||
boost::system::error_code ignoredEC;
|
||||
TCP_socket.shutdown(
|
||||
boost::asio::ip::tcp::socket::shutdown_both,
|
||||
ignoredEC
|
||||
);
|
||||
}
|
||||
}
|
||||
void handle_write(const boost::system::error_code& e);
|
||||
|
||||
void compressBufferCollection(
|
||||
std::vector<std::string> uncompressed_data,
|
||||
CompressionType compression_type,
|
||||
std::vector<char> & compressed_data
|
||||
) {
|
||||
boost::iostreams::gzip_params compression_parameters;
|
||||
|
||||
compression_parameters.level = boost::iostreams::zlib::best_speed;
|
||||
if ( deflateRFC1951 == compression_type ) {
|
||||
compression_parameters.noheader = true;
|
||||
}
|
||||
|
||||
BOOST_ASSERT( compressed_data.empty() );
|
||||
boost::iostreams::filtering_ostream compressing_stream;
|
||||
|
||||
compressing_stream.push(
|
||||
boost::iostreams::gzip_compressor(compression_parameters)
|
||||
);
|
||||
compressing_stream.push(
|
||||
boost::iostreams::back_inserter(compressed_data)
|
||||
);
|
||||
|
||||
BOOST_FOREACH( const std::string & line, uncompressed_data) {
|
||||
compressing_stream << line;
|
||||
}
|
||||
|
||||
compressing_stream.reset();
|
||||
}
|
||||
|
||||
// Big thanks to deusty who explains how to use gzip compression by
|
||||
// the right call to deflateInit2():
|
||||
// http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html
|
||||
// void compressCharArray(
|
||||
// const char * in_data,
|
||||
// size_t in_data_size,
|
||||
// std::vector<unsigned char> & buffer,
|
||||
// CompressionType type
|
||||
// ) {
|
||||
// const size_t BUFSIZE = 128 * 1024;
|
||||
// unsigned char temp_buffer[BUFSIZE];
|
||||
|
||||
// z_stream strm;
|
||||
// strm.zalloc = Z_NULL;
|
||||
// strm.zfree = Z_NULL;
|
||||
// strm.opaque = Z_NULL;
|
||||
// strm.total_out = 0;
|
||||
// strm.next_in = (unsigned char *)(in_data);
|
||||
// strm.avail_in = in_data_size;
|
||||
// strm.next_out = temp_buffer;
|
||||
// strm.avail_out = BUFSIZE;
|
||||
// strm.data_type = Z_ASCII;
|
||||
|
||||
// switch(type){
|
||||
// case deflateRFC1951:
|
||||
// deflateInit(&strm, Z_BEST_SPEED);
|
||||
// break;
|
||||
// case gzipRFC1952:
|
||||
// deflateInit2(
|
||||
// &strm,
|
||||
// Z_DEFAULT_COMPRESSION,
|
||||
// Z_DEFLATED,
|
||||
// (15+16),
|
||||
// 9,
|
||||
// Z_DEFAULT_STRATEGY
|
||||
// );
|
||||
// break;
|
||||
// default:
|
||||
// BOOST_ASSERT_MSG(false, "should not happen");
|
||||
// break;
|
||||
// }
|
||||
|
||||
// int deflate_res = Z_OK;
|
||||
// do {
|
||||
// if ( 0 == strm.avail_out ) {
|
||||
// buffer.insert(buffer.end(), temp_buffer, temp_buffer + BUFSIZE);
|
||||
// strm.next_out = temp_buffer;
|
||||
// strm.avail_out = BUFSIZE;
|
||||
// }
|
||||
// deflate_res = deflate(&strm, Z_FINISH);
|
||||
|
||||
// } while (deflate_res == Z_OK);
|
||||
|
||||
// BOOST_ASSERT_MSG(
|
||||
// deflate_res == Z_STREAM_END,
|
||||
// "compression not properly finished"
|
||||
// );
|
||||
|
||||
// buffer.insert(
|
||||
// buffer.end(),
|
||||
// temp_buffer,
|
||||
// temp_buffer + BUFSIZE - strm.avail_out
|
||||
// );
|
||||
// deflateEnd(&strm);
|
||||
// }
|
||||
|
||||
boost::asio::io_service::strand strand;
|
||||
boost::asio::ip::tcp::socket TCP_socket;
|
||||
RequestHandler& request_handler;
|
||||
boost::array<char, 8192> incoming_data_buffer;
|
||||
Request request;
|
||||
RequestParser request_parser;
|
||||
RequestParser * request_parser;
|
||||
Reply reply;
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//Exposes all data access interfaces to the algorithms via base class ptr
|
||||
|
||||
#include "../../DataStructures/Coordinate.h"
|
||||
#include "../../DataStructures/EdgeBasedNode.h"
|
||||
#include "../../DataStructures/ImportNode.h"
|
||||
#include "../../DataStructures/PhantomNodes.h"
|
||||
@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../../Util/StringUtil.h"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
template<class EdgeDataT>
|
||||
@ -113,7 +114,7 @@ public:
|
||||
std::string GetEscapedNameForNameID(const unsigned name_id) const {
|
||||
std::string temporary_string;
|
||||
GetName(name_id, temporary_string);
|
||||
return HTMLEntitize(temporary_string);
|
||||
return EscapeJSONString(temporary_string);
|
||||
}
|
||||
|
||||
virtual std::string GetTimestamp() const = 0;
|
||||
|
@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "BaseDataFacade.h"
|
||||
|
||||
#include "../../DataStructures/Coordinate.h"
|
||||
#include "../../DataStructures/OriginalEdgeData.h"
|
||||
#include "../../DataStructures/QueryNode.h"
|
||||
#include "../../DataStructures/QueryEdge.h"
|
||||
#include "../../DataStructures/SharedMemoryVectorWrapper.h"
|
||||
@ -40,10 +40,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../../DataStructures/StaticRTree.h"
|
||||
#include "../../Util/BoostFileSystemFix.h"
|
||||
#include "../../Util/GraphLoader.h"
|
||||
#include "../../Util/IniFile.h"
|
||||
#include "../../Util/ProgramOptions.h"
|
||||
#include "../../Util/SimpleLogger.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
template<class EdgeDataT>
|
||||
class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
|
||||
|
||||
@ -155,9 +156,9 @@ private:
|
||||
(char*)&(current_edge_data),
|
||||
sizeof(OriginalEdgeData)
|
||||
);
|
||||
m_via_node_list[i] = current_edge_data.viaNode;
|
||||
m_name_ID_list[i] = current_edge_data.nameID;
|
||||
m_turn_instruction_list[i] = current_edge_data.turnInstruction;
|
||||
m_via_node_list[i] = current_edge_data.via_node;
|
||||
m_name_ID_list[i] = current_edge_data.name_id;
|
||||
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
|
||||
}
|
||||
edges_input_stream.close();
|
||||
}
|
||||
|
@ -1,3 +1,33 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SHARED_BARRIER_H
|
||||
#define SHARED_BARRIER_H
|
||||
|
||||
#include <boost/interprocess/sync/named_mutex.hpp>
|
||||
#include <boost/interprocess/sync/named_condition.hpp>
|
||||
|
||||
@ -38,3 +68,5 @@ struct SharedBarriers {
|
||||
// Is there any query?
|
||||
int number_of_queries;
|
||||
};
|
||||
|
||||
#endif //SHARED_BARRIER_H
|
||||
|
@ -356,14 +356,14 @@ public:
|
||||
name_id < m_name_begin_indices.size(),
|
||||
"name id too high"
|
||||
);
|
||||
unsigned begin_index = m_name_begin_indices[name_id];
|
||||
unsigned end_index = m_name_begin_indices[name_id+1];
|
||||
const unsigned begin_index = m_name_begin_indices[name_id];
|
||||
const unsigned end_index = m_name_begin_indices[name_id+1];
|
||||
BOOST_ASSERT_MSG(
|
||||
begin_index < m_names_char_list.size(),
|
||||
begin_index <= m_names_char_list.size(),
|
||||
"begin index of name too high"
|
||||
);
|
||||
BOOST_ASSERT_MSG(
|
||||
end_index < m_names_char_list.size(),
|
||||
end_index <= m_names_char_list.size(),
|
||||
"end index of name too high"
|
||||
);
|
||||
|
||||
|
@ -31,7 +31,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "BaseDataFacade.h"
|
||||
|
||||
#include "../../DataStructures/Coordinate.h"
|
||||
#include "../../DataStructures/QueryEdge.h"
|
||||
#include "../../DataStructures/StaticGraph.h"
|
||||
#include "../../DataStructures/StaticRTree.h"
|
||||
@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/integer.hpp>
|
||||
|
||||
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;
|
||||
|
@ -25,7 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "Reply.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include "../../Util/StringUtil.h"
|
||||
|
||||
namespace http {
|
||||
|
||||
@ -38,6 +42,18 @@ void Reply::setSize(const unsigned size) {
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the size of the uncompressed output.
|
||||
void Reply::SetUncompressedSize()
|
||||
{
|
||||
unsigned uncompressed_size = 0;
|
||||
BOOST_FOREACH ( const std::string & current_line, content)
|
||||
{
|
||||
uncompressed_size += current_line.size();
|
||||
}
|
||||
setSize(uncompressed_size);
|
||||
}
|
||||
|
||||
|
||||
std::vector<boost::asio::const_buffer> Reply::toBuffers(){
|
||||
std::vector<boost::asio::const_buffer> buffers;
|
||||
buffers.push_back(ToBuffer(status));
|
||||
@ -88,25 +104,27 @@ Reply Reply::StockReply(Reply::status_type status) {
|
||||
}
|
||||
|
||||
std::string Reply::ToString(Reply::status_type status) {
|
||||
switch (status) {
|
||||
case Reply::ok:
|
||||
if (Reply::ok == status)
|
||||
{
|
||||
return okHTML;
|
||||
case Reply::badRequest:
|
||||
return badRequestHTML;
|
||||
default:
|
||||
return internalServerErrorHTML;
|
||||
}
|
||||
if (Reply::badRequest == status)
|
||||
{
|
||||
return badRequestHTML;
|
||||
}
|
||||
return internalServerErrorHTML;
|
||||
}
|
||||
|
||||
boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) {
|
||||
switch (status) {
|
||||
case Reply::ok:
|
||||
if (Reply::ok == status)
|
||||
{
|
||||
return boost::asio::buffer(okString);
|
||||
case Reply::internalServerError:
|
||||
return boost::asio::buffer(internalServerErrorString);
|
||||
default:
|
||||
return boost::asio::buffer(badRequestString);
|
||||
}
|
||||
if (Reply::internalServerError == status)
|
||||
{
|
||||
return boost::asio::buffer(internalServerErrorString);
|
||||
}
|
||||
return boost::asio::buffer(badRequestString);
|
||||
}
|
||||
|
||||
|
||||
|
113
Server/RequestHandler.cpp
Normal file
113
Server/RequestHandler.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "APIGrammar.h"
|
||||
#include "RequestHandler.h"
|
||||
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
RequestHandler::RequestHandler() : routing_machine(NULL) { }
|
||||
|
||||
void RequestHandler::handle_request(const http::Request& req, http::Reply& rep){
|
||||
//parse command
|
||||
try {
|
||||
std::string request;
|
||||
URIDecode(req.uri, request);
|
||||
|
||||
time_t ltime;
|
||||
struct tm *Tm;
|
||||
|
||||
ltime=time(NULL);
|
||||
Tm=localtime(<ime);
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
(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 << " " << req.endpoint.to_string() << " " <<
|
||||
req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
|
||||
req.agent << ( 0 == req.agent.length() ? "- " :" ") << request;
|
||||
|
||||
RouteParameters route_parameters;
|
||||
APIGrammarParser api_parser(&route_parameters);
|
||||
|
||||
std::string::iterator it = request.begin();
|
||||
const bool result = boost::spirit::qi::parse(
|
||||
it,
|
||||
request.end(),
|
||||
api_parser
|
||||
);
|
||||
|
||||
if ( !result || (it != request.end()) ) {
|
||||
rep = http::Reply::StockReply(http::Reply::badRequest);
|
||||
const int position = std::distance(request.begin(), it);
|
||||
std::string tmp_position_string;
|
||||
intToString(position, tmp_position_string);
|
||||
rep.content.push_back(
|
||||
"Input seems to be malformed close to position "
|
||||
"<br><pre>"
|
||||
);
|
||||
rep.content.push_back( request );
|
||||
rep.content.push_back(tmp_position_string);
|
||||
rep.content.push_back("<br>");
|
||||
const unsigned end = std::distance(request.begin(), it);
|
||||
for(unsigned i = 0; i < end; ++i) {
|
||||
rep.content.push_back(" ");
|
||||
}
|
||||
rep.content.push_back("^<br></pre>");
|
||||
} else {
|
||||
//parsing done, lets call the right plugin to handle the request
|
||||
BOOST_ASSERT_MSG(
|
||||
routing_machine != NULL,
|
||||
"pointer not init'ed"
|
||||
);
|
||||
routing_machine->RunQuery(route_parameters, rep);
|
||||
return;
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
rep = http::Reply::StockReply(http::Reply::internalServerError);
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"[server error] code: " << e.what() << ", uri: " << req.uri;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void RequestHandler::RegisterRoutingMachine(OSRM * osrm) {
|
||||
routing_machine = osrm;
|
||||
}
|
@ -28,95 +28,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef REQUEST_HANDLER_H
|
||||
#define REQUEST_HANDLER_H
|
||||
|
||||
#include "APIGrammar.h"
|
||||
#include "DataStructures/RouteParameters.h"
|
||||
#include "Http/Request.h"
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
template <typename Iterator, class HandlerT>
|
||||
struct APIGrammar;
|
||||
struct RouteParameters;
|
||||
class OSRM;
|
||||
|
||||
class RequestHandler : private boost::noncopyable {
|
||||
|
||||
public:
|
||||
typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
|
||||
explicit RequestHandler() : routing_machine(NULL) { }
|
||||
|
||||
void handle_request(const http::Request& req, http::Reply& rep){
|
||||
//parse command
|
||||
try {
|
||||
std::string request(req.uri);
|
||||
RequestHandler();
|
||||
|
||||
time_t ltime;
|
||||
struct tm *Tm;
|
||||
|
||||
ltime=time(NULL);
|
||||
Tm=localtime(<ime);
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
(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 << " " << req.endpoint.to_string() << " " <<
|
||||
req.referrer << ( 0 == req.referrer.length() ? "- " :" ") <<
|
||||
req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri;
|
||||
|
||||
RouteParameters routeParameters;
|
||||
APIGrammarParser apiParser(&routeParameters);
|
||||
|
||||
std::string::iterator it = request.begin();
|
||||
const bool result = boost::spirit::qi::parse(
|
||||
it,
|
||||
request.end(),
|
||||
apiParser
|
||||
);
|
||||
|
||||
if ( !result || (it != request.end()) ) {
|
||||
rep = http::Reply::StockReply(http::Reply::badRequest);
|
||||
const int position = std::distance(request.begin(), it);
|
||||
std::string tmp_position_string;
|
||||
intToString(position, tmp_position_string);
|
||||
rep.content.push_back(
|
||||
"Input seems to be malformed close to position "
|
||||
"<br><pre>"
|
||||
);
|
||||
rep.content.push_back( request );
|
||||
rep.content.push_back(tmp_position_string);
|
||||
rep.content.push_back("<br>");
|
||||
const unsigned end = std::distance(request.begin(), it);
|
||||
for(unsigned i = 0; i < end; ++i) {
|
||||
rep.content.push_back(" ");
|
||||
}
|
||||
rep.content.push_back("^<br></pre>");
|
||||
} else {
|
||||
//parsing done, lets call the right plugin to handle the request
|
||||
BOOST_ASSERT_MSG(
|
||||
routing_machine != NULL,
|
||||
"pointer not init'ed"
|
||||
);
|
||||
routing_machine->RunQuery(routeParameters, rep);
|
||||
return;
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
rep = http::Reply::StockReply(http::Reply::internalServerError);
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"[server error] code: " << e.what() << ", uri: " << req.uri;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
void RegisterRoutingMachine(OSRM * osrm) {
|
||||
routing_machine = osrm;
|
||||
}
|
||||
void handle_request(const http::Request& req, http::Reply& rep);
|
||||
void RegisterRoutingMachine(OSRM * osrm);
|
||||
|
||||
private:
|
||||
OSRM * routing_machine;
|
||||
|
@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "Http/Request.h"
|
||||
#include "RequestParser.h"
|
||||
|
||||
namespace http {
|
||||
|
@ -29,14 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define REQUEST_PARSER_H
|
||||
|
||||
#include "Http/CompressionType.h"
|
||||
#include "Http/Header.h"
|
||||
#include "Http/Request.h"
|
||||
#include <osrm/Header.h>
|
||||
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
namespace http {
|
||||
|
||||
struct Request;
|
||||
|
||||
class RequestParser {
|
||||
public:
|
||||
RequestParser();
|
||||
|
@ -29,23 +29,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define SERVERFACTORY_H_
|
||||
|
||||
#include "Server.h"
|
||||
#include "../Util/OpenMPWrapper.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <sstream>
|
||||
|
||||
struct ServerFactory : boost::noncopyable {
|
||||
static Server * CreateServer(std::string& ip_address, int ip_port, int threads) {
|
||||
static Server * CreateServer(
|
||||
std::string& ip_address,
|
||||
int ip_port,
|
||||
int threads
|
||||
) {
|
||||
|
||||
SimpleLogger().Write() <<
|
||||
"http 1.1 compression handled by zlib version " << zlibVersion();
|
||||
|
||||
std::stringstream port_stream;
|
||||
port_stream << ip_port;
|
||||
return new Server( ip_address, port_stream.str(), std::min( omp_get_num_procs(), threads) );
|
||||
std::string port_stream;
|
||||
intToString(ip_port, port_stream);
|
||||
|
||||
return new Server(
|
||||
ip_address,
|
||||
port_stream,
|
||||
std::min( omp_get_num_procs(), threads )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -79,6 +79,11 @@ int main (int argc, char * argv[]) {
|
||||
"starting up engines, " << g_GIT_DESCRIPTION << ", " <<
|
||||
"compiled at " << __DATE__ << ", " __TIME__;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
SimpleLogger().Write() << "Not supported on FreeBSD";
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if( 1 == argc ) {
|
||||
SimpleLogger().Write(logWARNING) <<
|
||||
"usage: " << argv[0] << " /path/on/device";
|
||||
@ -222,6 +227,12 @@ int main (int argc, char * argv[]) {
|
||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||
int ret2 = read(fileno(fd), (char*)&single_block[0], 4096);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int ret1 = lseek(f, current_offset, SEEK_SET);
|
||||
int ret2 = read(f, (char*)single_block, 4096);
|
||||
@ -281,6 +292,12 @@ int main (int argc, char * argv[]) {
|
||||
int ret1 = fseek(fd, current_offset, SEEK_SET);
|
||||
int ret2 = read(fileno(fd), (char*)&single_block, 4096);
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int ret1 = 0;
|
||||
int ret2 = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
int ret1 = lseek(f, current_offset, SEEK_SET);
|
||||
|
||||
|
@ -26,8 +26,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/GitDescription.h"
|
||||
#include "../Util/ProgramOptions.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
@ -37,15 +40,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#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)
|
||||
void print_tree(boost::property_tree::ptree const& property_tree, 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) {
|
||||
boost::property_tree::ptree::const_iterator end = property_tree.end();
|
||||
for (boost::property_tree::ptree::const_iterator tree_iterator = property_tree.begin(); tree_iterator != end; ++tree_iterator)
|
||||
{
|
||||
for (unsigned current_recursion = 0; current_recursion < recursion_depth; ++current_recursion)
|
||||
{
|
||||
std::cout << " " << std::flush;
|
||||
}
|
||||
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
|
||||
print_tree(it->second, recursion_depth+1);
|
||||
std::cout << tree_iterator->first << ": " << tree_iterator->second.get_value<std::string>() << std::endl;
|
||||
print_tree(tree_iterator->second, recursion_depth+1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,8 +59,8 @@ int main (int argc, const char * argv[]) {
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try {
|
||||
std::string ip_address;
|
||||
int ip_port, requested_num_threads;
|
||||
bool use_shared_memory = false;
|
||||
int ip_port, requested_thread_num;
|
||||
bool use_shared_memory = false, trial = false;
|
||||
ServerPaths server_paths;
|
||||
if( !GenerateServerProgramOptions(
|
||||
argc,
|
||||
@ -63,8 +68,9 @@ int main (int argc, const char * argv[]) {
|
||||
server_paths,
|
||||
ip_address,
|
||||
ip_port,
|
||||
requested_num_threads,
|
||||
use_shared_memory
|
||||
requested_thread_num,
|
||||
use_shared_memory,
|
||||
trial
|
||||
)
|
||||
) {
|
||||
return 0;
|
||||
@ -100,19 +106,20 @@ int main (int argc, const char * argv[]) {
|
||||
|
||||
//attention: super-inefficient hack below:
|
||||
|
||||
std::stringstream ss;
|
||||
BOOST_FOREACH(const std::string & line, osrm_reply.content) {
|
||||
std::stringstream my_stream;
|
||||
BOOST_FOREACH(const std::string & line, osrm_reply.content)
|
||||
{
|
||||
std::cout << line;
|
||||
ss << line;
|
||||
my_stream << line;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::read_json(ss, pt);
|
||||
boost::property_tree::ptree property_tree;
|
||||
boost::property_tree::read_json(my_stream, property_tree);
|
||||
|
||||
print_tree(pt, 0);
|
||||
} catch (std::exception & e) {
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what();
|
||||
print_tree(property_tree, 0);
|
||||
} catch (std::exception & current_exception) {
|
||||
SimpleLogger().Write(logWARNING) << "caught exception: " << current_exception.what();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -28,15 +28,87 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BOOST_FILE_SYSTEM_FIX_H
|
||||
#define BOOST_FILE_SYSTEM_FIX_H
|
||||
|
||||
#include "OSRMException.h"
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
//This is one big workaround for latest boost renaming woes.
|
||||
|
||||
#if BOOST_FILESYSTEM_VERSION < 3
|
||||
#warning Boost Installation with Filesystem3 missing, activating workaround
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
|
||||
// Validator for boost::filesystem::path, that verifies that the file
|
||||
// exists. The validate() function must be defined in the same namespace
|
||||
// as the target type, (boost::filesystem::path in this case), otherwise
|
||||
// it is not called
|
||||
// inline void validate(
|
||||
// boost::any & v,
|
||||
// const std::vector<std::string> & values,
|
||||
// boost::filesystem::path *,
|
||||
// int
|
||||
// ) {
|
||||
// boost::program_options::validators::check_first_occurrence(v);
|
||||
// const std::string & input_string =
|
||||
// boost::program_options::validators::get_single_string(values);
|
||||
// // SimpleLogger().Write() << "validator called for " << input_string;
|
||||
// // SimpleLogger().Write() << "validator called for " << input_string;
|
||||
// if(boost::filesystem::is_regular_file(input_string)) {
|
||||
// v = boost::any(boost::filesystem::path(input_string));
|
||||
// } else {
|
||||
// throw OSRMException(input_string + " not found");
|
||||
// }
|
||||
// }
|
||||
|
||||
// adapted from: http://stackoverflow.com/questions/1746136/how-do-i-normalize-a-pathname-using-boostfilesystem
|
||||
inline boost::filesystem::path portable_canonical(
|
||||
const boost::filesystem::path & relative_path,
|
||||
const boost::filesystem::path & current_path = boost::filesystem::current_path())
|
||||
{
|
||||
const boost::filesystem::path absolute_path = boost::filesystem::absolute(
|
||||
relative_path,
|
||||
current_path
|
||||
);
|
||||
|
||||
boost::filesystem::path canonical_path;
|
||||
for(
|
||||
boost::filesystem::path::const_iterator path_iterator = absolute_path.begin();
|
||||
path_iterator!=absolute_path.end();
|
||||
++path_iterator
|
||||
) {
|
||||
if( ".." == path_iterator->string() ) {
|
||||
// /a/b/.. is not necessarily /a if b is a symbolic link
|
||||
if( boost::filesystem::is_symlink(canonical_path) ) {
|
||||
canonical_path /= *path_iterator;
|
||||
} else if( ".." == canonical_path.filename() ) {
|
||||
// /a/b/../.. is not /a/b/.. under most circumstances
|
||||
// We can end up with ..s in our result because of symbolic links
|
||||
canonical_path /= *path_iterator;
|
||||
} else {
|
||||
// Otherwise it should be safe to resolve the parent
|
||||
canonical_path = canonical_path.parent_path();
|
||||
}
|
||||
} else if( "." == path_iterator->string() ) {
|
||||
// Ignore
|
||||
} else {
|
||||
// Just cat other path entries
|
||||
canonical_path /= *path_iterator;
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT( canonical_path.is_absolute() );
|
||||
BOOST_ASSERT( boost::filesystem::exists( canonical_path ) );
|
||||
return canonical_path;
|
||||
}
|
||||
|
||||
#if BOOST_FILESYSTEM_VERSION < 3
|
||||
|
||||
inline path temp_directory_path() {
|
||||
char * buffer;
|
||||
buffer = tmpnam (NULL);
|
||||
@ -48,10 +120,9 @@ inline path unique_path(const path&) {
|
||||
return temp_directory_path();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_FILESYSTEM_VERSION
|
||||
#define BOOST_FILESYSTEM_VERSION 3
|
||||
|
56
Util/ComputeAngle.h
Normal file
56
Util/ComputeAngle.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef COMPUTE_ANGLE_H
|
||||
#define COMPUTE_ANGLE_H
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <cmath>
|
||||
|
||||
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||
template<class CoordinateT>
|
||||
inline static 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 // COMPUTE_ANGLE_H
|
@ -50,5 +50,19 @@ inline void remove_consecutive_duplicates_from_vector(std::vector<T> & vector) {
|
||||
vector.resize(number_of_unique_elements);
|
||||
}
|
||||
|
||||
template< typename FwdIter, typename Func >
|
||||
Func for_each_pair( FwdIter iter_begin, FwdIter iter_end, Func func ) {
|
||||
if( iter_begin == iter_end ) {
|
||||
return func;
|
||||
}
|
||||
|
||||
FwdIter iter_next = iter_begin;
|
||||
++iter_next;
|
||||
|
||||
for( ; iter_next != iter_end; ++iter_begin, ++iter_next ){
|
||||
func( *iter_begin, *iter_next );
|
||||
}
|
||||
return func;
|
||||
}
|
||||
|
||||
#endif /* CONTAINERUTILS_H_ */
|
||||
|
336
Util/DataStoreOptions.h
Normal file
336
Util/DataStoreOptions.h
Normal file
@ -0,0 +1,336 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DATA_STORE_OPTIONS_H
|
||||
#define DATA_STORE_OPTIONS_H
|
||||
|
||||
#include "BoostFileSystemFix.h"
|
||||
#include "GitDescription.h"
|
||||
#include "OSRMException.h"
|
||||
#include "SimpleLogger.h"
|
||||
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
void AssertPathExists(const boost::filesystem::path& path)
|
||||
{
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << path << " check failed";
|
||||
throw OSRMException(path.string() + " not found.");
|
||||
} else {
|
||||
SimpleLogger().Write(logDEBUG) << path << " exists";
|
||||
}
|
||||
}
|
||||
|
||||
// support old capitalized option names by down-casing them with a regex replace
|
||||
inline void PrepareConfigFile(
|
||||
const boost::filesystem::path & path,
|
||||
std::string & output
|
||||
) {
|
||||
boost::filesystem::fstream config_stream(path);
|
||||
std::string input_str(
|
||||
(std::istreambuf_iterator<char>(config_stream)),
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
boost::regex regex("^([^=]*)"); //match from start of line to '='
|
||||
std::string format("\\L$1\\E"); //replace with downcased substring
|
||||
output = boost::regex_replace( input_str, regex, format );
|
||||
}
|
||||
|
||||
// generate boost::program_options object for the routing part
|
||||
inline bool GenerateDataStoreOptions(const int argc, const char * argv[], ServerPaths & paths)
|
||||
{
|
||||
// declare a group of options that will be allowed only on command line
|
||||
boost::program_options::options_description generic_options("Options");
|
||||
generic_options.add_options()
|
||||
("version,v", "Show version")
|
||||
("help,h", "Show this help message")
|
||||
(
|
||||
"config,c",
|
||||
boost::program_options::value<boost::filesystem::path>(
|
||||
&paths["config"]
|
||||
)->default_value("server.ini"),
|
||||
"Path to a configuration file"
|
||||
);
|
||||
|
||||
// declare a group of options that will be allowed both on command line
|
||||
// as well as in a config file
|
||||
boost::program_options::options_description config_options("Configuration");
|
||||
config_options.add_options()
|
||||
(
|
||||
"hsgrdata",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["hsgrdata"]),
|
||||
".hsgr file"
|
||||
)
|
||||
(
|
||||
"nodesdata",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["nodesdata"]),
|
||||
".nodes file"
|
||||
)
|
||||
(
|
||||
"edgesdata",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["edgesdata"]),
|
||||
".edges file"
|
||||
)
|
||||
// (
|
||||
// "geometry",
|
||||
// boost::program_options::value<boost::filesystem::path>(&paths["geometries"]),
|
||||
// ".geometry file"
|
||||
// )
|
||||
(
|
||||
"ramindex",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["ramindex"]),
|
||||
".ramIndex file"
|
||||
)
|
||||
(
|
||||
"fileindex",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["fileindex"]),
|
||||
".fileIndex file"
|
||||
)
|
||||
(
|
||||
"namesdata",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["namesdata"]),
|
||||
".names file"
|
||||
)
|
||||
(
|
||||
"timestamp",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["timestamp"]),
|
||||
".timestamp file"
|
||||
);
|
||||
|
||||
// hidden options, will be allowed both on command line and in config
|
||||
// file, but will not be shown to the user
|
||||
boost::program_options::options_description hidden_options("Hidden options");
|
||||
hidden_options.add_options()
|
||||
(
|
||||
"base,b",
|
||||
boost::program_options::value<boost::filesystem::path>(&paths["base"]),
|
||||
"base path to .osrm file"
|
||||
);
|
||||
|
||||
// positional option
|
||||
boost::program_options::positional_options_description positional_options;
|
||||
positional_options.add("base", 1);
|
||||
|
||||
// combine above options for parsing
|
||||
boost::program_options::options_description cmdline_options;
|
||||
cmdline_options.add(generic_options).add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description config_file_options;
|
||||
config_file_options.add(config_options).add(hidden_options);
|
||||
|
||||
boost::program_options::options_description visible_options(
|
||||
boost::filesystem::basename(argv[0]) + " [<options>] <configuration>"
|
||||
);
|
||||
visible_options.add(generic_options).add(config_options);
|
||||
|
||||
// parse command line options
|
||||
boost::program_options::variables_map option_variables;
|
||||
boost::program_options::store
|
||||
(
|
||||
boost::program_options::command_line_parser(argc, argv).options(cmdline_options).positional(positional_options).run(),
|
||||
option_variables
|
||||
);
|
||||
|
||||
if(option_variables.count("version"))
|
||||
{
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(option_variables.count("help"))
|
||||
{
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
|
||||
const bool parameter_present =
|
||||
(paths.find("hsgrdata") != paths.end() && !paths.find("hsgrdata")->second.string().empty() ) ||
|
||||
(paths.find("nodesdata") != paths.end() && !paths.find("nodesdata")->second.string().empty()) ||
|
||||
(paths.find("edgesdata") != paths.end() && !paths.find("edgesdata")->second.string().empty()) ||
|
||||
// (paths.find("geometry") != paths.end() && !paths.find("geometry")->second.string().empty())) ||
|
||||
(paths.find("ramindex") != paths.end() && !paths.find("ramindex")->second.string().empty()) ||
|
||||
(paths.find("fileindex") != paths.end() && !paths.find("fileindex")->second.string().empty()) ||
|
||||
(paths.find("timestamp") != paths.end() && !paths.find("timestamp")->second.string().empty()) ;
|
||||
|
||||
if (parameter_present)
|
||||
{
|
||||
if (
|
||||
( paths.find("config") != paths.end() &&
|
||||
boost::filesystem::is_regular_file(paths.find("config")->second)
|
||||
) || option_variables.count("base")
|
||||
)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "conflicting parameters";
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// parse config file
|
||||
ServerPaths::iterator path_iterator = paths.find("config");
|
||||
if (
|
||||
path_iterator != paths.end() &&
|
||||
boost::filesystem::is_regular_file(path_iterator->second) &&
|
||||
!option_variables.count("base")
|
||||
)
|
||||
{
|
||||
SimpleLogger().Write() << "Reading options from: " << path_iterator->second.string();
|
||||
std::string config_str;
|
||||
PrepareConfigFile( path_iterator->second, config_str );
|
||||
std::stringstream config_stream( config_str );
|
||||
boost::program_options::store(
|
||||
parse_config_file(config_stream, config_file_options),
|
||||
option_variables
|
||||
);
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
else if (option_variables.count("base"))
|
||||
{
|
||||
path_iterator = paths.find("base");
|
||||
BOOST_ASSERT( paths.end() != path_iterator );
|
||||
std::string base_string = path_iterator->second.string();
|
||||
|
||||
path_iterator = paths.find("hsgrdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".hsgr";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("nodesdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".nodes";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("edgesdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".edges";
|
||||
}
|
||||
|
||||
// path_iterator = paths.find("geometries");
|
||||
// if (path_iterator != paths.end())
|
||||
// {
|
||||
// path_iterator->second = base_string + ".geometry";
|
||||
// }
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".ramIndex";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("fileindex");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".fileIndex";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("namesdata");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".names";
|
||||
}
|
||||
|
||||
path_iterator = paths.find("timestamp");
|
||||
if (path_iterator != paths.end())
|
||||
{
|
||||
path_iterator->second = base_string + ".timestamp";
|
||||
}
|
||||
}
|
||||
|
||||
path_iterator = paths.find("hsgrdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".hsgr file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("nodesdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".nodes file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("edgesdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".edges file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
// path_iterator = paths.find("geometries");
|
||||
// if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
// {
|
||||
// path_iterator->second = base_string + ".geometry";
|
||||
// }
|
||||
// AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".ramindex file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("fileindex");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".fileindex file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("namesdata");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".names file must be specified");
|
||||
}
|
||||
AssertPathExists(path_iterator->second);
|
||||
|
||||
path_iterator = paths.find("timestamp");
|
||||
if (path_iterator == paths.end() || path_iterator->second.string().empty())
|
||||
{
|
||||
throw OSRMException(".timestamp file must be specified");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* DATA_STORE_OPTIONS_H */
|
@ -25,4 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GIT_DESCRIPTION_H
|
||||
#define GIT_DESCRIPTION_H
|
||||
|
||||
extern char g_GIT_DESCRIPTION[];
|
||||
|
||||
#endif //GIT_DESCRIPTION_H
|
||||
|
100
Util/IniFile.cpp
Normal file
100
Util/IniFile.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "IniFile.h"
|
||||
|
||||
#include "OSRMException.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
IniFile::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 IniFile::GetParameter(const std::string & key){
|
||||
return parameters.Find(key);
|
||||
}
|
||||
|
||||
std::string IniFile::GetParameter(const std::string & key) const {
|
||||
return parameters.Find(key);
|
||||
}
|
||||
|
||||
bool IniFile::Holds(const std::string & key) const {
|
||||
return parameters.Holds(key);
|
||||
}
|
||||
|
||||
void IniFile::SetParameter(const char* key, const char* value) {
|
||||
SetParameter(std::string(key), std::string(value));
|
||||
}
|
||||
|
||||
void IniFile::SetParameter(const std::string & key, const std::string & value) {
|
||||
parameters.insert(std::make_pair(key, value));
|
||||
}
|
||||
|
||||
void IniFile::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);
|
||||
}
|
||||
}
|
@ -28,82 +28,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#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>
|
||||
#include <vector>
|
||||
|
||||
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);
|
||||
}
|
||||
IniFile(const char * config_filename);
|
||||
|
||||
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);
|
||||
|
||||
std::string GetParameter(const std::string & key){
|
||||
return parameters.Find(key);
|
||||
}
|
||||
std::string GetParameter(const std::string & key) const;
|
||||
|
||||
std::string GetParameter(const std::string & key) const {
|
||||
return parameters.Find(key);
|
||||
}
|
||||
bool Holds(const std::string & key) const;
|
||||
|
||||
bool Holds(const std::string & key) const {
|
||||
return parameters.Holds(key);
|
||||
}
|
||||
void SetParameter(const char* key, const char* value);
|
||||
|
||||
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));
|
||||
}
|
||||
void SetParameter(const std::string & key, const std::string & 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;
|
||||
};
|
||||
|
@ -1,160 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef LINUXSTACKTRACE_H_
|
||||
#define LINUXSTACKTRACE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <cxxabi.h>
|
||||
#include <execinfo.h>
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
std::string binaryName;
|
||||
|
||||
std::string getFileAndLine (char * offset_end) {
|
||||
std::string a(offset_end);
|
||||
std::string result;
|
||||
a = a.substr(2,a.length()-3);
|
||||
static char buf[256];
|
||||
std::string command("/usr/bin/addr2line -C -e " + binaryName + " -f -i " + a);
|
||||
// prepare command to be executed
|
||||
// our program need to be passed after the -e parameter
|
||||
FILE* f = popen (command.c_str(), "r");
|
||||
|
||||
if (f == NULL) {
|
||||
perror (buf);
|
||||
return "";
|
||||
}
|
||||
// get function name
|
||||
if ( NULL != fgets (buf, 256, f) ) {
|
||||
|
||||
// get file and line
|
||||
if ( NULL != fgets (buf, 256, f) ) {
|
||||
|
||||
if (buf[0] != '?') {
|
||||
result = ( buf);
|
||||
} else {
|
||||
result = "unkown";
|
||||
}
|
||||
} else { result = ""; }
|
||||
} else { result = ""; }
|
||||
pclose(f);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void crashHandler(int sig_num, siginfo_t * info, void * ) {
|
||||
const size_t maxDepth = 100;
|
||||
//size_t stackDepth;
|
||||
|
||||
void *stackAddrs[maxDepth];
|
||||
backtrace(stackAddrs, maxDepth);
|
||||
|
||||
std::cerr << "signal " << sig_num << " (" << strsignal(sig_num) << "), address is " << info->si_addr << " from " << stackAddrs[0] << std::endl;
|
||||
|
||||
void * array[50];
|
||||
int size = backtrace(array, 50);
|
||||
|
||||
array[1] = stackAddrs[0];
|
||||
|
||||
char ** messages = backtrace_symbols(array, size);
|
||||
|
||||
// skip first stack frame (points here)
|
||||
for (int i = 1; i < size-1 && messages != NULL; ++i) {
|
||||
char *mangledname = 0, *offset_begin = 0, *offset_end = 0;
|
||||
|
||||
// find parantheses and +address offset surrounding mangled name
|
||||
for (char *p = messages[i+1]; *p; ++p) {
|
||||
if (*p == '(') {
|
||||
mangledname = p;
|
||||
} else if (*p == '+') {
|
||||
offset_begin = p;
|
||||
} else if (*p == ')') {
|
||||
offset_end = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if the line could be processed, attempt to demangle the symbol
|
||||
if (mangledname && offset_begin && offset_end && mangledname < offset_begin) {
|
||||
*mangledname++ = '\0';
|
||||
*offset_begin++ = '\0';
|
||||
*offset_end++ = '\0';
|
||||
|
||||
int status;
|
||||
char * real_name = abi::__cxa_demangle(mangledname, 0, 0, &status);
|
||||
|
||||
// if demangling is successful, output the demangled function name
|
||||
if (status == 0) {
|
||||
std::cerr << "[bt]: (" << i << ") " << messages[i+1] << " : " << real_name << " " << getFileAndLine(offset_end);
|
||||
}
|
||||
// otherwise, output the mangled function name
|
||||
else {
|
||||
std::cerr << "[bt]: (" << i << ") " << messages[i+1] << " : "
|
||||
<< mangledname << "+" << offset_begin << offset_end
|
||||
<< std::endl;
|
||||
}
|
||||
free(real_name);
|
||||
}
|
||||
// otherwise, print the whole line
|
||||
else {
|
||||
std::cerr << "[bt]: (" << i << ") " << messages[i+1] << std::endl;
|
||||
}
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
||||
free(messages);
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void installCrashHandler(std::string b) {
|
||||
binaryName = b;
|
||||
#ifndef NDEBUG
|
||||
struct sigaction sigact;
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
sigact.sa_sigaction = crashHandler;
|
||||
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
|
||||
if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0) {
|
||||
std::cerr << "error setting signal handler for " << SIGSEGV << " " << strsignal(SIGSEGV) << std::endl;
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
inline void installCrashHandler(std::string ) {}
|
||||
#endif
|
||||
#endif /* LINUXSTACKTRACE_H_ */
|
@ -28,15 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef MACHINE_INFO_H
|
||||
#define MACHINE_INFO_H
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
extern "C" {
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
}
|
||||
#elif defined _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
enum Endianness {
|
||||
LittleEndian = 1,
|
||||
BigEndian = 2
|
||||
@ -46,8 +37,9 @@ enum Endianness {
|
||||
inline Endianness getMachineEndianness() {
|
||||
int i(1);
|
||||
char *p = (char *) &i;
|
||||
if (1 == p[0])
|
||||
if (1 == p[0]) {
|
||||
return LittleEndian;
|
||||
}
|
||||
return BigEndian;
|
||||
}
|
||||
|
||||
@ -58,36 +50,4 @@ inline unsigned swapEndian(unsigned x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// Returns the physical memory size in kilobytes
|
||||
inline unsigned GetPhysicalmemory(void){
|
||||
#if defined(SUN5) || defined(__linux__)
|
||||
return (sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE));
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
int mib[2] = {CTL_HW, HW_MEMSIZE};
|
||||
long long memsize;
|
||||
size_t len = sizeof(memsize);
|
||||
sysctl(mib, 2, &memsize, &len, NULL, 0);
|
||||
return memsize/1024;
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
int mib[2] = {CTL_HW, HW_PHYSMEM};
|
||||
long long memsize;
|
||||
size_t len = sizeof(memsize);
|
||||
sysctl(mib, 2, &memsize, &len, NULL, 0);
|
||||
return memsize/1024;
|
||||
|
||||
#elif defined(_WIN32)
|
||||
MEMORYSTATUSEX status;
|
||||
status.dwLength = sizeof(status);
|
||||
GlobalMemoryStatusEx(&status);
|
||||
return status.ullTotalPhys/1024;
|
||||
#else
|
||||
std::cout << "[Warning] Compiling on unknown architecture." << std::endl
|
||||
<< "Please file a ticket at http://project-osrm.org" << std::endl;
|
||||
return 2048*1024; /* 128 Mb default memory */
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif // MACHINE_INFO_H
|
||||
|
||||
|
@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "OSRMException.h"
|
||||
#include "SimpleLogger.h"
|
||||
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
@ -40,36 +42,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef boost::unordered_map<
|
||||
const std::string,
|
||||
boost::filesystem::path
|
||||
> ServerPaths;
|
||||
|
||||
namespace boost {
|
||||
namespace filesystem {
|
||||
// Validator for boost::filesystem::path, that verifies that the file
|
||||
// exists. The validate() function must be defined in the same namespace
|
||||
// as the target type, (boost::filesystem::path in this case), otherwise
|
||||
// it is not called
|
||||
inline void validate(
|
||||
boost::any & v,
|
||||
const std::vector<std::string> & values,
|
||||
boost::filesystem::path *,
|
||||
int
|
||||
) {
|
||||
boost::program_options::validators::check_first_occurrence(v);
|
||||
const std::string & input_string =
|
||||
boost::program_options::validators::get_single_string(values);
|
||||
if(boost::filesystem::is_regular_file(input_string)) {
|
||||
v = boost::any(boost::filesystem::path(input_string));
|
||||
} else {
|
||||
throw OSRMException(input_string + " not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const static unsigned INIT_OK_START_ENGINE = 0;
|
||||
const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
|
||||
const static unsigned INIT_FAILED = -1;
|
||||
|
||||
// support old capitalized option names by down-casing them with a regex replace
|
||||
inline void PrepareConfigFile(
|
||||
@ -86,16 +62,16 @@ inline void PrepareConfigFile(
|
||||
output = boost::regex_replace( input_str, regex, format );
|
||||
}
|
||||
|
||||
|
||||
// generate boost::program_options object for the routing part
|
||||
inline bool GenerateServerProgramOptions(
|
||||
inline unsigned GenerateServerProgramOptions(
|
||||
const int argc,
|
||||
const char * argv[],
|
||||
ServerPaths & paths,
|
||||
std::string & ip_address,
|
||||
int & ip_port,
|
||||
int & requested_num_threads,
|
||||
bool & use_shared_memory
|
||||
bool & use_shared_memory,
|
||||
bool & trial
|
||||
) {
|
||||
|
||||
// declare a group of options that will be allowed only on command line
|
||||
@ -109,6 +85,11 @@ inline bool GenerateServerProgramOptions(
|
||||
&paths["config"]
|
||||
)->default_value("server.ini"),
|
||||
"Path to a configuration file"
|
||||
)
|
||||
(
|
||||
"trial",
|
||||
boost::program_options::value<bool>(&trial)->implicit_value(true),
|
||||
"Quit after initialization"
|
||||
);
|
||||
|
||||
// declare a group of options that will be allowed both on command line
|
||||
@ -162,7 +143,7 @@ inline bool GenerateServerProgramOptions(
|
||||
)
|
||||
(
|
||||
"sharedmemory,s",
|
||||
boost::program_options::value<bool>(&use_shared_memory)->default_value(false),
|
||||
boost::program_options::value<bool>(&use_shared_memory)->implicit_value(true),
|
||||
"Load data from shared memory"
|
||||
);
|
||||
|
||||
@ -201,12 +182,12 @@ inline bool GenerateServerProgramOptions(
|
||||
|
||||
if(option_variables.count("version")) {
|
||||
SimpleLogger().Write() << g_GIT_DESCRIPTION;
|
||||
return false;
|
||||
return INIT_OK_DO_NOT_START_ENGINE;
|
||||
}
|
||||
|
||||
if(option_variables.count("help")) {
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return false;
|
||||
return INIT_OK_DO_NOT_START_ENGINE;
|
||||
}
|
||||
|
||||
boost::program_options::notify(option_variables);
|
||||
@ -221,7 +202,7 @@ inline bool GenerateServerProgramOptions(
|
||||
SimpleLogger().Write() <<
|
||||
"Reading options from: " << path_iterator->second.string();
|
||||
std::string config_str;
|
||||
PrepareConfigFile( paths["config"], config_str );
|
||||
PrepareConfigFile( path_iterator->second, config_str );
|
||||
std::stringstream config_stream( config_str );
|
||||
boost::program_options::store(
|
||||
parse_config_file(config_stream, config_file_options),
|
||||
@ -230,14 +211,23 @@ inline bool GenerateServerProgramOptions(
|
||||
boost::program_options::notify(option_variables);
|
||||
}
|
||||
|
||||
if( 1 > requested_num_threads ) {
|
||||
throw OSRMException("Number of threads must be a positive number");
|
||||
}
|
||||
|
||||
if( !use_shared_memory && option_variables.count("base") ) {
|
||||
std::string base_string = paths["base"].string();
|
||||
path_iterator = paths.find("base");
|
||||
BOOST_ASSERT( paths.end() != path_iterator );
|
||||
std::string base_string = path_iterator->second.string();
|
||||
|
||||
path_iterator = paths.find("hsgrdata");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".hsgr";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".hsgr not found");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("nodesdata");
|
||||
@ -246,38 +236,52 @@ inline bool GenerateServerProgramOptions(
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".nodes";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".nodes not found");
|
||||
}
|
||||
|
||||
|
||||
path_iterator = paths.find("edgesdata");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".edges";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".edges not found");
|
||||
}
|
||||
|
||||
|
||||
path_iterator = paths.find("ramindex");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".ramIndex";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".ramIndex not found");
|
||||
}
|
||||
|
||||
|
||||
path_iterator = paths.find("fileindex");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".fileIndex";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".fileIndex not found");
|
||||
}
|
||||
|
||||
|
||||
path_iterator = paths.find("namesdata");
|
||||
if(
|
||||
path_iterator != paths.end() &&
|
||||
!boost::filesystem::is_regular_file(path_iterator->second)
|
||||
) {
|
||||
path_iterator->second = base_string + ".names";
|
||||
} else {
|
||||
throw OSRMException(base_string + ".namesIndex not found");
|
||||
}
|
||||
|
||||
path_iterator = paths.find("timestamp");
|
||||
@ -287,12 +291,15 @@ inline bool GenerateServerProgramOptions(
|
||||
) {
|
||||
path_iterator->second = base_string + ".timestamp";
|
||||
}
|
||||
}
|
||||
|
||||
if( 1 > requested_num_threads ) {
|
||||
throw OSRMException("Number of threads must be a positive number");
|
||||
return INIT_OK_START_ENGINE;
|
||||
}
|
||||
return true;
|
||||
if (use_shared_memory && !option_variables.count("base"))
|
||||
{
|
||||
return INIT_OK_START_ENGINE;
|
||||
}
|
||||
SimpleLogger().Write() << visible_options;
|
||||
return INIT_OK_DO_NOT_START_ENGINE;
|
||||
}
|
||||
|
||||
#endif /* PROGRAM_OPTIONS_H */
|
||||
|
@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
|
||||
// precision: position after decimal point
|
||||
@ -159,6 +160,47 @@ inline void stringSplit(
|
||||
boost::split(result, s, boost::is_any_of(std::string(&delim)));
|
||||
}
|
||||
|
||||
inline std::string EscapeJSONString(const std::string& input) {
|
||||
std::string output;
|
||||
output.reserve(input.size());
|
||||
for(
|
||||
std::string::const_iterator iter = input.begin();
|
||||
iter != input.end();
|
||||
++iter
|
||||
) {
|
||||
switch (iter[0]) {
|
||||
case '\\':
|
||||
output += "\\\\";
|
||||
break;
|
||||
case '"':
|
||||
output += "\\\"";
|
||||
break;
|
||||
case '/':
|
||||
output += "\\/";
|
||||
break;
|
||||
case '\b':
|
||||
output += "\\b";
|
||||
break;
|
||||
case '\f':
|
||||
output += "\\f";
|
||||
break;
|
||||
case '\n':
|
||||
output += "\\n";
|
||||
break;
|
||||
case '\r':
|
||||
output += "\\r";
|
||||
break;
|
||||
case '\t':
|
||||
output += "\\t";
|
||||
break;
|
||||
default:
|
||||
output += *iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
static std::string originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"};
|
||||
static std::string entities[] = {"&", """, "<", ">", "'", "&91;", "&93;", " \" };
|
||||
|
||||
@ -177,6 +219,36 @@ inline std::string HTMLDeEntitize( std::string & result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::size_t URIDecode(const std::string & input, std::string & output) {
|
||||
std::string::const_iterator src_iter = input.begin();
|
||||
output.resize(input.size()+1);
|
||||
std::size_t decoded_length = 0;
|
||||
for( decoded_length = 0; src_iter != input.end(); ++decoded_length ) {
|
||||
if(
|
||||
src_iter[0] == '%' &&
|
||||
src_iter[1] &&
|
||||
src_iter[2] &&
|
||||
isxdigit(src_iter[1]) &&
|
||||
isxdigit(src_iter[2])
|
||||
) {
|
||||
std::string::value_type a = src_iter[1];
|
||||
std::string::value_type b = src_iter[2];
|
||||
a -= src_iter[1] < 58 ? 48 : src_iter[1] < 71 ? 55 : 87;
|
||||
b -= src_iter[2] < 58 ? 48 : src_iter[2] < 71 ? 55 : 87;
|
||||
output[decoded_length] = 16 * a + b;
|
||||
src_iter += 3;
|
||||
continue;
|
||||
}
|
||||
output[decoded_length] = *src_iter++;
|
||||
}
|
||||
output.resize(decoded_length);
|
||||
return decoded_length;
|
||||
}
|
||||
|
||||
inline std::size_t URIDecodeInPlace(std::string & URI) {
|
||||
return URIDecode(URI, URI);
|
||||
}
|
||||
|
||||
inline bool StringStartsWith(
|
||||
const std::string & input,
|
||||
const std::string & prefix
|
||||
@ -184,4 +256,18 @@ inline bool StringStartsWith(
|
||||
return boost::starts_with(input, prefix);
|
||||
}
|
||||
|
||||
inline std::string GetRandomString() {
|
||||
char s[128];
|
||||
static const char alphanum[] =
|
||||
"0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
for (int i = 0; i < 127; ++i) {
|
||||
s[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
|
||||
}
|
||||
s[127] = 0;
|
||||
return std::string(s);
|
||||
}
|
||||
|
||||
#endif /* STRINGUTIL_H_ */
|
||||
|
29
cmake/CheckCXXCompilerFlag.cmake
Normal file
29
cmake/CheckCXXCompilerFlag.cmake
Normal file
@ -0,0 +1,29 @@
|
||||
# - Check whether the CXX compiler supports a given flag.
|
||||
# CHECK_CXX_COMPILER_FLAG(<flag> <var>)
|
||||
# <flag> - the compiler flag
|
||||
# <var> - variable to store the result
|
||||
# This internally calls the check_cxx_source_compiles macro. See help
|
||||
# for CheckCXXSourceCompiles for a listing of variables that can
|
||||
# modify the build.
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
MACRO (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
|
||||
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
CHECK_CXX_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT}
|
||||
# Some compilers do not fail with a bad flag
|
||||
FAIL_REGEX "unrecognized .*option" # GNU
|
||||
FAIL_REGEX "ignoring unknown option" # MSVC
|
||||
FAIL_REGEX "[Uu]nknown option" # HP
|
||||
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
|
||||
FAIL_REGEX "command option .* is not recognized" # XL
|
||||
)
|
||||
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
ENDMACRO (CHECK_CXX_COMPILER_FLAG)
|
11
cmake/pkgconfig.in
Normal file
11
cmake/pkgconfig.in
Normal file
@ -0,0 +1,11 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
includedir=${prefix}/include/osrm
|
||||
libdir=${prefix}/lib
|
||||
|
||||
Name: libOSRM
|
||||
Description: Project OSRM library
|
||||
Version: @GIT_DESCRIPTION@
|
||||
Requires:
|
||||
Libs: -L${libdir} -lOSRM
|
||||
Libs.private: @BOOST_LIBRARY_LISTING@
|
||||
Cflags: -I${includedir}
|
@ -2,7 +2,8 @@
|
||||
##YAML Template
|
||||
---
|
||||
default: --require features --tags ~@todo --tags ~@bug --tag ~@stress
|
||||
verify: --require features --tags ~@todo --tags ~@bug --tag ~@stress -f progress
|
||||
verify: --require features --tags ~@todo --tags ~@bug --tags ~@stress -f progress
|
||||
jenkins: --require features --tags ~@todo --tags ~@bug --tags ~@stress --tags ~@options -f progress
|
||||
bugs: --require features --tags @bug
|
||||
todo: --require features --tags @todo
|
||||
all: --require features
|
@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "DataStructures/OriginalEdgeData.h"
|
||||
#include "DataStructures/QueryEdge.h"
|
||||
#include "DataStructures/SharedMemoryFactory.h"
|
||||
#include "DataStructures/SharedMemoryVectorWrapper.h"
|
||||
@ -34,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "Server/DataStructures/SharedDataType.h"
|
||||
#include "Server/DataStructures/SharedBarriers.h"
|
||||
#include "Util/BoostFileSystemFix.h"
|
||||
#include "Util/ProgramOptions.h"
|
||||
#include "Util/DataStoreOptions.h"
|
||||
#include "Util/SimpleLogger.h"
|
||||
#include "Util/UUID.h"
|
||||
#include "typedefs.h"
|
||||
@ -50,8 +51,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <vector>
|
||||
|
||||
int main( const int argc, const char * argv[] ) {
|
||||
SharedBarriers barrier;
|
||||
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
SharedBarriers barrier;
|
||||
|
||||
#ifdef __linux__
|
||||
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
|
||||
@ -60,6 +62,7 @@ int main( const int argc, const char * argv[] ) {
|
||||
}
|
||||
#endif
|
||||
|
||||
try {
|
||||
try {
|
||||
boost::interprocess::scoped_lock<
|
||||
boost::interprocess::named_mutex
|
||||
@ -68,24 +71,19 @@ int main( const int argc, const char * argv[] ) {
|
||||
// hard unlock in case of any exception.
|
||||
barrier.pending_update_mutex.unlock();
|
||||
}
|
||||
try {
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
|
||||
} catch(const std::exception & e) {
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
}
|
||||
|
||||
bool use_shared_memory = false;
|
||||
std::string ip_address;
|
||||
int ip_port, requested_num_threads;
|
||||
try {
|
||||
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
|
||||
|
||||
ServerPaths server_paths;
|
||||
if(
|
||||
!GenerateServerProgramOptions(
|
||||
!GenerateDataStoreOptions(
|
||||
argc,
|
||||
argv,
|
||||
server_paths,
|
||||
ip_address,
|
||||
ip_port,
|
||||
requested_num_threads,
|
||||
use_shared_memory
|
||||
server_paths
|
||||
)
|
||||
) {
|
||||
return 0;
|
||||
@ -124,7 +122,8 @@ int main( const int argc, const char * argv[] ) {
|
||||
paths_iterator = server_paths.find("fileindex");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
const std::string & file_index_file_name = paths_iterator->second.string();
|
||||
const boost::filesystem::path index_file_path_absolute = boost::filesystem::portable_canonical(paths_iterator->second);
|
||||
const std::string & file_index_file_name = index_file_path_absolute.string();
|
||||
paths_iterator = server_paths.find("nodesdata");
|
||||
BOOST_ASSERT(server_paths.end() != paths_iterator);
|
||||
BOOST_ASSERT(!paths_iterator->second.empty());
|
||||
@ -160,7 +159,7 @@ int main( const int argc, const char * argv[] ) {
|
||||
shared_layout_ptr->ram_index_file_name
|
||||
);
|
||||
// add zero termination
|
||||
unsigned end_of_string_index = std::min(1023ul, file_index_file_name.length());
|
||||
unsigned end_of_string_index = std::min((std::size_t)1023, file_index_file_name.length());
|
||||
shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0';
|
||||
|
||||
// collect number of elements to store in shared memory object
|
||||
@ -324,9 +323,9 @@ int main( const int argc, const char * argv[] ) {
|
||||
(char*)&(current_edge_data),
|
||||
sizeof(OriginalEdgeData)
|
||||
);
|
||||
via_node_ptr[i] = current_edge_data.viaNode;
|
||||
name_id_ptr[i] = current_edge_data.nameID;
|
||||
turn_instructions_ptr[i] = current_edge_data.turnInstruction;
|
||||
via_node_ptr[i] = current_edge_data.via_node;
|
||||
name_id_ptr[i] = current_edge_data.name_id;
|
||||
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
|
||||
}
|
||||
edges_input_stream.close();
|
||||
|
||||
@ -379,7 +378,7 @@ int main( const int argc, const char * argv[] ) {
|
||||
);
|
||||
hsgr_input_stream.close();
|
||||
|
||||
//TODO acquire lock
|
||||
// acquire lock
|
||||
SharedMemory * data_type_memory = SharedMemoryFactory::Get(
|
||||
CURRENT_REGIONS,
|
||||
sizeof(SharedDataTimestamp),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user