Merge branch 'develop' for release v0.3.8

This commit is contained in:
Dennis Luxen 2014-04-04 15:35:37 +02:00
commit 966f1d654e
166 changed files with 5692 additions and 3490 deletions

1
.gitignore vendored
View File

@ -77,6 +77,7 @@ stxxl.errlog
/osrm-routed /osrm-routed
/osrm-datastore /osrm-datastore
/osrm-prepare /osrm-prepare
/osrm-unlock-all
/osrm-cli /osrm-cli
/nohup.out /nohup.out

View File

@ -5,21 +5,32 @@ compiler:
# Make sure CMake is installed # Make sure CMake is installed
install: install:
- sudo apt-get update >/dev/null - sudo apt-get update >/dev/null
- sudo apt-get -q install libprotoc-dev libprotobuf7 protobuf-compiler libprotobuf-dev libosmpbf-dev libpng12-dev libbz2-dev libstxxl-dev libstxxl-doc libstxxl1 libxml2-dev libzip-dev libboost1.46-all-dev lua5.1 liblua5.1-0-dev libluabind-dev rubygems osmosis - sudo apt-get -q install libprotoc-dev libprotobuf7 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: before_script:
- sudo gem install bundler - rvm use 1.9.3
- gem install bundler
- bundle install - bundle install
- mkdir build - mkdir build
- cd build - cd build
- cmake .. $CMAKEOPTIONS - cmake .. $CMAKEOPTIONS
script: make script:
- make -j 2
- cd ..
- cucumber -p verify
after_script:
# - cd ..
# - cucumber -p verify
branches: branches:
only: only:
- master - master
- develop - develop
cache:
- bundler
- apt
env: env:
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Release" OSRM_PORT=5000 OSRM_TIMEOUT=60
- CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" - CMAKEOPTIONS="-DCMAKE_BUILD_TYPE=Debug" OSRM_PORT=5010 OSRM_TIMEOUT=60
notifications: notifications:
irc: irc:
channels: channels:

View File

@ -26,60 +26,92 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "DouglasPeucker.h" #include "DouglasPeucker.h"
#include "../DataStructures/SegmentInformation.h"
#include "../Util/MercatorUtil.h"
#include <limits>
//These thresholds are more or less heuristically chosen. //These thresholds are more or less heuristically chosen.
static double DouglasPeuckerThresholds[19] = { static double DouglasPeuckerThresholds[19] = {
32000000., //z0 262144., //z0
16240000., //z1 131072., //z1
8240000., //z2 65536., //z2
4240000., //z3 32768., //z3
2000000., //z4 16384., //z4
1000000., //z5 8192., //z5
500000., //z6 4096., //z6
240000., //z7 2048., //z7
120000., //z8 960., //z8
60000., //z9 480., //z9
30000., //z10 240., //z10
19000., //z11 90., //z11
5000., //z12 50., //z12
2000., //z13 25., //z13
200., //z14 15., //z14
16., //z15 5., //z15
6., //z16 .65, //z16
3., //z17 .5, //z17
3. //z18 .35 //z18
}; };
/** /**
* This distance computation does integer arithmetic only and is about twice as * Yuck! Code duplication. This function is also in EgdeBasedNode.h
* fast as the other distance function. It is an approximation only, but works
* more or less ok.
*/ */
int DouglasPeucker::fastDistance( double DouglasPeucker::ComputeDistance(
const FixedPointCoordinate& point, const FixedPointCoordinate& point,
const FixedPointCoordinate& segA, const FixedPointCoordinate& segA,
const FixedPointCoordinate& segB const FixedPointCoordinate& segB
) const { ) const {
const int p2x = (segB.lon - segA.lon); const double x = lat2y(point.lat/COORDINATE_PRECISION);
const int p2y = (segB.lat - segA.lat); const double y = point.lon/COORDINATE_PRECISION;
const int something = p2x*p2x + p2y*p2y; const double a = lat2y(segA.lat/COORDINATE_PRECISION);
double u = ( 0 == something ? 0 : ((point.lon - segA.lon) * p2x + (point.lat - segA.lat) * p2y) / something); 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) { //discretize the result to coordinate precision. it's a hack!
u = 1; if( std::abs(nY) < (1./COORDINATE_PRECISION) ) {
} else if (u < 0) { nY = 0.;
u = 0;
} }
const int x = segA.lon + u * p2x; double r = (p - nY*a)/c;
const int y = segA.lat + u * p2y; if( std::isnan(r) ) {
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
const int dx = x - point.lon; } else if( std::abs(r) <= std::numeric_limits<double>::epsilon() ) {
const int dy = y - point.lat; r = 0.;
} else if( std::abs(r-1.) <= std::numeric_limits<double>::epsilon() ) {
const int dist = (dx*dx + dy*dy); r = 1.;
}
return dist; 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( void DouglasPeucker::Run(
@ -91,7 +123,7 @@ void DouglasPeucker::Run(
BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid"); BOOST_ASSERT_MSG(1 < input_geometry.size(), "geometry invalid");
std::size_t left_border = 0; std::size_t left_border = 0;
std::size_t right_border = 1; 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 { do {
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
input_geometry[left_border].necessary, input_geometry[left_border].necessary,
@ -109,7 +141,7 @@ void DouglasPeucker::Run(
++right_border; ++right_border;
} while( right_border < input_geometry.size()); } while( right_border < input_geometry.size());
} }
while(!recursion_stack.empty()) { while( !recursion_stack.empty() ) {
//pop next element //pop next element
const PairOfPoints pair = recursion_stack.top(); const PairOfPoints pair = recursion_stack.top();
recursion_stack.pop(); recursion_stack.pop();
@ -129,17 +161,17 @@ void DouglasPeucker::Run(
pair.first < pair.second, pair.first < pair.second,
"left border on the wrong side" "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; std::size_t farthest_element_index = pair.second;
//find index idx of element with max_distance //find index idx of element with max_distance
for(std::size_t i = pair.first+1; i < pair.second; ++i){ 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[i].location,
input_geometry[pair.first].location, input_geometry[pair.first].location,
input_geometry[pair.second].location input_geometry[pair.second].location
); );
const double distance = std::fabs(temp_dist); const double distance = std::abs(temp_dist);
if( if(
distance > DouglasPeuckerThresholds[zoom_level] && distance > DouglasPeuckerThresholds[zoom_level] &&
distance > max_distance distance > max_distance

View File

@ -28,10 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef DOUGLASPEUCKER_H_ #ifndef DOUGLASPEUCKER_H_
#define DOUGLASPEUCKER_H_ #define DOUGLASPEUCKER_H_
#include "../DataStructures/Coordinate.h" #include "../Util/SimpleLogger.h"
#include "../DataStructures/SegmentInformation.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include <cmath> #include <cmath>
@ -39,30 +41,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stack> #include <stack>
#include <vector> #include <vector>
/*This class object computes the bitvector of indicating generalized input points /* This class object computes the bitvector of indicating generalized input
* according to the (Ramer-)Douglas-Peucker algorithm. * points according to the (Ramer-)Douglas-Peucker algorithm.
* *
* Input is vector of pairs. Each pair consists of the point information and a bit * Input is vector of pairs. Each pair consists of the point information and a
* indicating if the points is present in the generalization. * bit indicating if the points is present in the generalization.
* Note: points may also be pre-selected*/ * Note: points may also be pre-selected*/
struct SegmentInformation;
class DouglasPeucker { class DouglasPeucker {
private: private:
typedef std::pair<std::size_t, std::size_t> PairOfPoints; typedef std::pair<std::size_t, std::size_t> PairOfPoints;
//Stack to simulate the recursion //Stack to simulate the recursion
std::stack<PairOfPoints > recursion_stack; std::stack<PairOfPoints> recursion_stack;
/** double ComputeDistance(
* 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(
const FixedPointCoordinate& point, const FixedPointCoordinate& point,
const FixedPointCoordinate& segA, const FixedPointCoordinate& segA,
const FixedPointCoordinate& segB const FixedPointCoordinate& segB
) const; ) const;
public: public:
void Run(std::vector<SegmentInformation> & input_geometry, const unsigned zoom_level); void Run(
std::vector<SegmentInformation> & input_geometry,
const unsigned zoom_level
);
}; };

View File

@ -25,32 +25,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef ITERATORBASEDCRC32_H_ #ifndef ITERATOR_BASED_CRC32_H
#define ITERATORBASEDCRC32_H_ #define ITERATOR_BASED_CRC32_H
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iostream> #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> template<class ContainerT>
class IteratorbasedCRC32 { class IteratorbasedCRC32 {
private: private:
typedef typename ContainerT::iterator ContainerT_iterator; typedef typename ContainerT::iterator IteratorType;
unsigned crc; unsigned crc;
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type; bool use_SSE42_CRC_function;
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){ #if !defined(__x86_64__)
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_Processor; boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
CRC32_Processor.process_bytes( str, len); #endif
return CRC32_Processor.checksum(); 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), // adapted from http://byteworm.com/2010/10/13/crc32/
r=len%sizeof(unsigned), unsigned SSE42BasedCRC32( char *str, unsigned len )
*p=(unsigned*)str/*, crc*/; {
#if defined(__x86_64__)
unsigned q = len/sizeof(unsigned);
unsigned r = len%sizeof(unsigned);
unsigned *p = (unsigned*)str;
//crc=0; //crc=0;
while (q--) { while (q--) {
@ -71,47 +94,55 @@ private:
); );
++str; ++str;
} }
#endif
return crc; return crc;
} }
unsigned cpuid(unsigned functionInput){ inline unsigned cpuid() const
unsigned eax; {
unsigned ebx; unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
unsigned ecx; // on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
unsigned edx; __get_cpuid( 1, &eax, &ebx, &ecx, &edx );
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (functionInput));
return ecx; return ecx;
} }
CRC32CFunctionPtr detectBestCRC32C(){ bool DetectNativeCRC32Support()
static const int SSE42_BIT = 20; {
unsigned ecx = cpuid(1); static const int SSE42_BIT = 0x00100000;
bool hasSSE42 = ecx & (1 << SSE42_BIT); const unsigned ecx = cpuid();
if (hasSSE42) { const bool has_SSE42 = ecx & SSE42_BIT;
if (has_SSE42) {
SimpleLogger().Write() << "using hardware based CRC32 computation"; SimpleLogger().Write() << "using hardware based CRC32 computation";
return &IteratorbasedCRC32::SSEBasedCRC32; //crc32 hardware accelarated;
} else { } else {
SimpleLogger().Write() << "using software based CRC32 computation"; SimpleLogger().Write() << "using software based CRC32 computation";
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
} }
return has_SSE42;
} }
CRC32CFunctionPtr crcFunction;
public: public:
IteratorbasedCRC32(): crc(0) { IteratorbasedCRC32() : crc(0)
crcFunction = detectBestCRC32C(); {
use_SSE42_CRC_function = DetectNativeCRC32Support();
} }
virtual ~IteratorbasedCRC32() { } unsigned operator()( IteratorType iter, const IteratorType end )
{
unsigned operator()( ContainerT_iterator iter, const ContainerT_iterator end) {
unsigned crc = 0; unsigned crc = 0;
while(iter != end) { while(iter != end) {
char * data = reinterpret_cast<char*>(&(*iter) ); char * data = reinterpret_cast<char*>(&(*iter) );
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; ++iter;
} }
return crc; return crc;
} }
}; };
#endif /* ITERATORBASEDCRC32_H_ */ #endif /* ITERATOR_BASED_CRC32_H */

View File

@ -108,10 +108,10 @@ void PolylineCompressor::printUnencodedString(
output += "["; output += "[";
std::string tmp; std::string tmp;
for(unsigned i = 0; i < polyline.size(); i++) { for(unsigned i = 0; i < polyline.size(); i++) {
convertInternalLatLonToString(polyline[i].lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
output += "["; output += "[";
output += tmp; output += tmp;
convertInternalLatLonToString(polyline[i].lon, tmp); FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
output += ", "; output += ", ";
output += tmp; output += tmp;
output += "]"; output += "]";
@ -132,10 +132,10 @@ void PolylineCompressor::printUnencodedString(
if(!polyline[i].necessary) { if(!polyline[i].necessary) {
continue; continue;
} }
convertInternalLatLonToString(polyline[i].location.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
output += "["; output += "[";
output += tmp; output += tmp;
convertInternalLatLonToString(polyline[i].location.lon, tmp); FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
output += ", "; output += ", ";
output += tmp; output += tmp;
output += "]"; output += "]";

View File

@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STRONGLYCONNECTEDCOMPONENTS_H_ #ifndef STRONGLYCONNECTEDCOMPONENTS_H_
#define STRONGLYCONNECTEDCOMPONENTS_H_ #define STRONGLYCONNECTEDCOMPONENTS_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h" #include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/ImportEdge.h" #include "../DataStructures/ImportEdge.h"
@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
@ -385,7 +386,7 @@ public:
} }
const TarjanDynamicGraph::NodeIterator v = m_node_based_graph->GetTarget(e1); 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].lat,
m_coordinate_list[u].lon, m_coordinate_list[u].lon,
m_coordinate_list[v].lat, m_coordinate_list[v].lat,

View File

@ -1,58 +1,73 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
project(OSRM) project(OSRM)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXCompilerFlag)
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(GetGitRevisionDescription) include(GetGitRevisionDescription)
git_describe(GIT_DESCRIPTION) 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(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 add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/UUID.cpp UUID.cpp.alwaysbuild
COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/UUID-Config.cmake
DEPENDS DEPENDS
${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in ${CMAKE_SOURCE_DIR}/Util/UUID.cpp.in
${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake ${CMAKE_SOURCE_DIR}/cmake/UUID-Config.cmake
COMMENT "Configuring UUID.cpp" COMMENT "Configuring UUID.cpp"
VERBATIM) 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) file(GLOB ExtractorGlob Extractor/*.cpp)
set(ExtractorSources extractor.cpp ${ExtractorGlob}) set(ExtractorSources extractor.cpp ${ExtractorGlob})
add_executable(osrm-extract ${ExtractorSources} ) add_executable(osrm-extract ${ExtractorSources})
file( GLOB PrepareGlob Contractor/*.cpp ) file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp)
set( PrepareSources prepare.cpp ${PrepareGlob} ) set(PrepareSources prepare.cpp ${PrepareGlob})
add_executable( osrm-prepare ${PrepareSources} ) add_executable(osrm-prepare ${PrepareSources})
file(GLOB ServerGlob Server/*.cpp) file(GLOB ServerGlob Server/*.cpp)
file(GLOB DescriptorGlob Descriptors/*.cpp) file(GLOB DescriptorGlob Descriptors/*.cpp)
file(GLOB DatastructureGlob DataStructures/*.cpp) file(GLOB DatastructureGlob DataStructures/SearchEngineData.cpp)
file(GLOB CoordinateGlob DataStructures/Coordinate.cpp)
file(GLOB AlgorithmGlob Algorithms/*.cpp) file(GLOB AlgorithmGlob Algorithms/*.cpp)
file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp)
file(GLOB LibOSRMGlob Library/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp)
set(OSRMSources ${LibOSRMGlob} ${DescriptorGlob} ${DatastructureGlob} ${AlgorithmGlob} ${HttpGlob}) set(
add_library( OSRM SHARED ${OSRMSources} ) OSRMSources
add_library( UUID STATIC Util/UUID.cpp ) ${LibOSRMGlob}
add_library( GITDESCRIPTION STATIC Util/GitDescription.cpp ) ${DescriptorGlob}
add_dependencies( UUID UUIDConfigure ) ${DatastructureGlob}
add_dependencies( GITDESCRIPTION GIT_DESCRIPTION ) ${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}) add_executable(osrm-routed routed.cpp ${ServerGlob})
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED) set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
@ -60,148 +75,195 @@ add_executable(osrm-datastore datastore.cpp)
# Check the release mode # Check the release mode
if(NOT CMAKE_BUILD_TYPE MATCHES Debug) if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug) endif()
if(CMAKE_BUILD_TYPE MATCHES Debug) if(CMAKE_BUILD_TYPE MATCHES Debug)
message(STATUS "Configuring OSRM in debug mode") 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) if(CMAKE_BUILD_TYPE MATCHES Release)
message(STATUS "Configuring OSRM in release mode") message(STATUS "Configuring OSRM in release mode")
endif(CMAKE_BUILD_TYPE MATCHES Release)
# 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() endif()
# Configuring compilers # Configuring compilers
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# using Clang # using Clang
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC")
message(STATUS "OpenMP parallelization not available using clang++") message(STATUS "OpenMP parallelization not available using clang++")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC # using GCC
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fopenmp -pedantic -fPIC")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++ # using Intel C++
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-intel -wd10237 -Wall -openmp -ipo -fPIC")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++ # using Visual Studio C++
endif() 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 # Configuring other platform dependencies
if(APPLE) if(APPLE)
SET(CMAKE_OSX_ARCHITECTURES "x86_64") set(CMAKE_OSX_ARCHITECTURES "x86_64")
message(STATUS "Set Architecture to x64 on OS X") message(STATUS "Set Architecture to x64 on OS X")
EXEC_PROGRAM(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION) exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
STRING(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION}) string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
IF (DARWIN_VERSION GREATER 12) if(DARWIN_VERSION GREATER 12 AND NOT OSXLIBSTD)
MESSAGE(STATUS "Activating -std=c++11 flag for >= OS X 10.9") message(STATUS "Activating -std=c++11 flag for >= OS X 10.9")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
ENDIF (DARWIN_VERSION GREATER 12) 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() endif()
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
target_link_libraries( osrm-datastore rt ) target_link_libraries(osrm-datastore rt)
target_link_libraries( OSRM rt ) target_link_libraries(OSRM rt)
endif(UNIX AND NOT APPLE) endif()
#Check Boost #Check Boost
set(BOOST_MIN_VERSION "1.44.0") set(BOOST_MIN_VERSION "1.46.0")
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED ) find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED)
if (NOT Boost_FOUND) if(NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n") message(FATAL_ERROR "Fatal error: Boost (version >= 1.46.0) required.\n")
endif (NOT Boost_FOUND) endif()
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
IF( APPLE ) target_link_libraries(OSRM ${Boost_LIBRARIES} COORDLIB)
target_link_libraries( OSRM ${Boost_LIBRARIES} UUID ) target_link_libraries(osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
ELSE( APPLE ) target_link_libraries(osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries( OSRM ${Boost_LIBRARIES} ) target_link_libraries(osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
ENDIF( APPLE ) target_link_libraries(osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
target_link_libraries( osrm-extract ${Boost_LIBRARIES} UUID GITDESCRIPTION )
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} UUID GITDESCRIPTION )
target_link_libraries( osrm-routed ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION )
target_link_libraries( osrm-datastore ${Boost_LIBRARIES} UUID GITDESCRIPTION )
find_package ( BZip2 REQUIRED ) find_package(Threads REQUIRED)
include_directories(${BZIP_INCLUDE_DIRS}) target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
find_package( ZLIB REQUIRED ) find_package(Lua52)
include_directories(${ZLIB_INCLUDE_DIRS}) if(NOT LUA52_FOUND)
target_link_libraries (osrm-extract ${ZLIB_LIBRARY}) find_package(Lua51 REQUIRED)
target_link_libraries (osrm-routed ${ZLIB_LIBRARY}) if(NOT APPLE)
find_package(LuaJIT 5.1)
endif()
else()
if(NOT APPLE)
find_package(LuaJIT 5.2)
endif()
endif()
find_package( Threads REQUIRED ) if( LUAJIT_FOUND )
target_link_libraries (osrm-extract ${Threads_LIBRARY}) target_link_libraries(osrm-extract ${LUAJIT_LIBRARIES})
target_link_libraries(osrm-prepare ${LUAJIT_LIBRARIES})
find_package( Lua52 ) else()
IF ( NOT LUA52_FOUND ) target_link_libraries(osrm-extract ${LUA_LIBRARY})
find_package( Lua51 REQUIRED ) target_link_libraries(osrm-prepare ${LUA_LIBRARY})
IF (NOT APPLE) endif()
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 ()
include_directories(${LUA_INCLUDE_DIR}) include_directories(${LUA_INCLUDE_DIR})
find_package(LibXml2 REQUIRED)
find_package( LibXml2 REQUIRED )
include_directories(${LIBXML2_INCLUDE_DIR}) include_directories(${LIBXML2_INCLUDE_DIR})
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES}) target_link_libraries(osrm-extract ${LIBXML2_LIBRARIES})
find_package( Luabind REQUIRED ) find_package( Luabind REQUIRED )
include_directories(${LUABIND_INCLUDE_DIR}) include_directories(${LUABIND_INCLUDE_DIR})
target_link_libraries (osrm-extract ${LUABIND_LIBRARY}) target_link_libraries(osrm-extract ${LUABIND_LIBRARY})
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY}) target_link_libraries(osrm-prepare ${LUABIND_LIBRARY})
find_package( Protobuf REQUIRED )
include_directories(${PROTOBUF_INCLUDE_DIRS})
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
find_package( STXXL REQUIRED ) find_package( STXXL REQUIRED )
include_directories(${STXXL_INCLUDE_DIR}) include_directories(${STXXL_INCLUDE_DIR})
target_link_libraries (OSRM ${STXXL_LIBRARY}) target_link_libraries(OSRM ${STXXL_LIBRARY})
target_link_libraries (osrm-extract ${STXXL_LIBRARY}) target_link_libraries(osrm-extract ${STXXL_LIBRARY})
target_link_libraries (osrm-prepare ${STXXL_LIBRARY}) target_link_libraries(osrm-prepare ${STXXL_LIBRARY})
find_package( OSMPBF REQUIRED ) find_package( OSMPBF REQUIRED )
include_directories(${OSMPBF_INCLUDE_DIR}) include_directories(${OSMPBF_INCLUDE_DIR})
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY}) target_link_libraries(osrm-extract ${OSMPBF_LIBRARY})
target_link_libraries (osrm-prepare ${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) if(WITH_TOOLS)
message(STATUS "Activating OSRM internal tools") message(STATUS "Activating OSRM internal tools")
find_package( GDAL ) find_package(GDAL)
if(GDAL_FOUND) if(GDAL_FOUND)
add_executable(osrm-components Tools/componentAnalysis.cpp) add_executable(osrm-components Tools/componentAnalysis.cpp)
include_directories(${GDAL_INCLUDE_DIR}) include_directories(${GDAL_INCLUDE_DIR})
target_link_libraries( target_link_libraries(
osrm-components ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION osrm-components
) ${GDAL_LIBRARIES} ${Boost_LIBRARIES} UUID GITDESCRIPTION COORDLIB)
endif(GDAL_FOUND) endif()
add_executable ( osrm-cli Tools/simpleclient.cpp) add_executable(osrm-cli Tools/simpleclient.cpp)
target_link_libraries( osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION ) target_link_libraries(osrm-cli ${Boost_LIBRARIES} OSRM UUID GITDESCRIPTION)
add_executable ( osrm-io-benchmark Tools/io-benchmark.cpp ) add_executable(osrm-io-benchmark Tools/io-benchmark.cpp)
target_link_libraries( osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION) target_link_libraries(osrm-io-benchmark ${Boost_LIBRARIES} GITDESCRIPTION)
add_executable ( osrm-unlock-all Tools/unlock_all_mutexes.cpp ) add_executable(osrm-unlock-all Tools/unlock_all_mutexes.cpp)
target_link_libraries( osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION) target_link_libraries(osrm-unlock-all ${Boost_LIBRARIES} GITDESCRIPTION)
if(UNIX AND NOT APPLE) if(UNIX AND NOT APPLE)
target_link_libraries( osrm-unlock-all rt ) target_link_libraries(osrm-unlock-all rt)
endif(UNIX AND NOT APPLE) endif()
endif(WITH_TOOLS) 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)

View File

@ -45,8 +45,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <ctime>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include <vector> #include <vector>
@ -54,10 +52,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class Contractor { class Contractor {
private: private:
struct _ContractorEdgeData { struct ContractorEdgeData {
_ContractorEdgeData() : ContractorEdgeData() :
distance(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), originalViaNodeID(false) {} 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) {} distance(_distance), id(_id), originalEdges(std::min((unsigned)1<<28, _originalEdges) ), shortcut(_shortcut), forward(_forward), backward(_backward), originalViaNodeID(false) {}
unsigned distance; unsigned distance;
unsigned id; unsigned id;
@ -75,7 +73,7 @@ private:
_HeapData( short h, bool t ) : hop(h), target(t) {} _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, ArrayStorage<NodeID, NodeID> > _Heap;
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID> > _Heap; typedef BinaryHeap< NodeID, NodeID, int, _HeapData, XORFastHashStorage<NodeID, NodeID> > _Heap;
typedef _DynamicGraph::InputEdge _ContractorEdge; typedef _DynamicGraph::InputEdge _ContractorEdge;
@ -118,6 +116,7 @@ public:
Contractor( int nodes, ContainerT& inputEdges) { Contractor( int nodes, ContainerT& inputEdges) {
std::vector< _ContractorEdge > edges; std::vector< _ContractorEdge > edges;
edges.reserve(inputEdges.size()*2); edges.reserve(inputEdges.size()*2);
temp_edge_counter = 0;
typename ContainerT::deallocation_iterator diter = inputEdges.dbegin(); typename ContainerT::deallocation_iterator diter = inputEdges.dbegin();
typename ContainerT::deallocation_iterator dend = inputEdges.dend(); typename ContainerT::deallocation_iterator dend = inputEdges.dend();
@ -126,7 +125,7 @@ public:
while(diter!=dend) { while(diter!=dend) {
newEdge.source = diter->source(); newEdge.source = diter->source();
newEdge.target = diter->target(); newEdge.target = diter->target();
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward()); newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" ); BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
#ifndef NDEBUG #ifndef NDEBUG
@ -195,6 +194,7 @@ public:
_graph = boost::make_shared<_DynamicGraph>( nodes, edges ); _graph = boost::make_shared<_DynamicGraph>( nodes, edges );
edges.clear(); edges.clear();
std::vector<_ContractorEdge>().swap(edges); std::vector<_ContractorEdge>().swap(edges);
BOOST_ASSERT( 0 == edges.capacity() );
// unsigned maxdegree = 0; // unsigned maxdegree = 0;
// NodeID highestNode = 0; // NodeID highestNode = 0;
// //
@ -214,14 +214,14 @@ public:
//Create temporary file //Create temporary file
// GetTemporaryFileName(temporaryEdgeStorageFilename); // GetTemporaryFileName(temporaryEdgeStorageFilename);
temporaryStorageSlotID = TemporaryStorage::GetInstance().allocateSlot(); edge_storage_slot = TemporaryStorage::GetInstance().AllocateSlot();
std::cout << "contractor finished initalization" << std::endl; std::cout << "contractor finished initalization" << std::endl;
} }
~Contractor() { ~Contractor() {
//Delete temporary file //Delete temporary file
// remove(temporaryEdgeStorageFilename.c_str()); // remove(temporaryEdgeStorageFilename.c_str());
TemporaryStorage::GetInstance().deallocateSlot(temporaryStorageSlotID); TemporaryStorage::GetInstance().DeallocateSlot(edge_storage_slot);
} }
void Run() { void Run() {
@ -264,11 +264,11 @@ public:
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush; std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
//Delete old heap data to free memory that we need for the coming operations //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; delete data;
}
threadData.clear(); threadData.clear();
//Create new priority array //Create new priority array
std::vector<float> newNodePriority(remainingNodes.size()); 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 //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; remainingNodes[newNodeID].id = newNodeID;
} }
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); 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 //walk over all nodes
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) { for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
const NodeID start = i; const NodeID start = i;
@ -299,11 +293,11 @@ public:
const NodeID target = _graph->GetTarget(currentEdge); const NodeID target = _graph->GetTarget(currentEdge);
if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){ if(UINT_MAX == newNodeIDFromOldNodeIDMap[i] ){
//Save edges of this node w/o renumbering. //Save edges of this node w/o renumbering.
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); tempStorage.WriteToSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); tempStorage.WriteToSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); tempStorage.WriteToSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
++numberOfTemporaryEdges; ++temp_edge_counter;
}else { } else {
//node is not yet contracted. //node is not yet contracted.
//add (renumbered) outgoing edges to new DynamicGraph. //add (renumbered) outgoing edges to new DynamicGraph.
_ContractorEdge newEdge; _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. //Delete map from old NodeIDs to new ones.
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap); std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
@ -394,10 +385,14 @@ public:
_DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target); _DynamicGraph::EdgeIterator currentEdgeID = _graph->FindEdge(edge.source, edge.target);
if(currentEdgeID < _graph->EndEdges(edge.source) ) { if(currentEdgeID < _graph->EndEdges(edge.source) ) {
_DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID); _DynamicGraph::EdgeData & currentEdgeData = _graph->GetEdgeData(currentEdgeID);
if( currentEdgeData.shortcut if( currentEdgeData.shortcut &&
&& edge.data.forward == currentEdgeData.forward edge.data.forward == currentEdgeData.forward &&
&& edge.data.backward == currentEdgeData.backward ) { edge.data.backward == currentEdgeData.backward &&
currentEdgeData.distance = std::min(currentEdgeData.distance, edge.data.distance); 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; continue;
} }
} }
@ -454,13 +449,13 @@ public:
SimpleLogger().Write() << "Getting edges of minimized graph"; SimpleLogger().Write() << "Getting edges of minimized graph";
NodeID numberOfNodes = _graph->GetNumberOfNodes(); NodeID numberOfNodes = _graph->GetNumberOfNodes();
if(_graph->GetNumberOfNodes()) { if(_graph->GetNumberOfNodes()) {
Edge newEdge;
for ( NodeID node = 0; node < numberOfNodes; ++node ) { for ( NodeID node = 0; node < numberOfNodes; ++node ) {
p.printStatus(node); p.printStatus(node);
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) { for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
const NodeID target = _graph->GetTarget( edge ); const NodeID target = _graph->GetTarget( edge );
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge ); const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
Edge newEdge; if( !oldNodeIDFromNewNodeIDMap.empty() ) {
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
newEdge.source = oldNodeIDFromNewNodeIDMap[node]; newEdge.source = oldNodeIDFromNewNodeIDMap[node];
newEdge.target = oldNodeIDFromNewNodeIDMap[target]; newEdge.target = oldNodeIDFromNewNodeIDMap[target];
} else { } else {
@ -477,7 +472,10 @@ public:
); );
newEdge.data.distance = data.distance; newEdge.data.distance = data.distance;
newEdge.data.shortcut = data.shortcut; newEdge.data.shortcut = data.shortcut;
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) { if(
!data.originalViaNodeID &&
!oldNodeIDFromNewNodeIDMap.empty()
) {
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id]; newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
} else { } else {
newEdge.data.id = data.id; newEdge.data.id = data.id;
@ -494,31 +492,29 @@ public:
} }
_graph.reset(); _graph.reset();
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap); std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
BOOST_ASSERT( 0 == oldNodeIDFromNewNodeIDMap.capacity() );
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance(); 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. //loads edges of graph before renumbering, no need for further numbering action.
NodeID start; NodeID start;
NodeID target; NodeID target;
//edges.reserve(edges.size()+numberOfTemporaryEdges);
_DynamicGraph::EdgeData data; _DynamicGraph::EdgeData data;
for(unsigned i = 0; i < numberOfTemporaryEdges; ++i) {
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&start, sizeof(NodeID)); Edge restored_edge;
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&target, sizeof(NodeID)); for(unsigned i = 0; i < temp_edge_counter; ++i) {
tempStorage.readFromSlot(temporaryStorageSlotID, (char*)&data, sizeof(_DynamicGraph::EdgeData)); tempStorage.ReadFromSlot(edge_storage_slot, (char*)&start, sizeof(NodeID));
Edge newEdge; tempStorage.ReadFromSlot(edge_storage_slot, (char*)&target, sizeof(NodeID));
newEdge.source = start; tempStorage.ReadFromSlot(edge_storage_slot, (char*)&data, sizeof(_DynamicGraph::EdgeData));
newEdge.target = target; restored_edge.source = start;
newEdge.data.distance = data.distance; restored_edge.target = target;
newEdge.data.shortcut = data.shortcut; restored_edge.data.distance = data.distance;
newEdge.data.id = data.id; restored_edge.data.shortcut = data.shortcut;
newEdge.data.forward = data.forward; restored_edge.data.id = data.id;
newEdge.data.backward = data.backward; restored_edge.data.forward = data.forward;
edges.push_back( newEdge ); restored_edge.data.backward = data.backward;
edges.push_back( restored_edge );
} }
tempStorage.deallocateSlot(temporaryStorageSlotID); tempStorage.DeallocateSlot(edge_storage_slot);
} }
private: private:
@ -548,7 +544,7 @@ private:
//iterate over all edges of node //iterate over all edges of node
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) { for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
const _ContractorEdgeData& data = _graph->GetEdgeData( edge ); const ContractorEdgeData& data = _graph->GetEdgeData( edge );
if ( !data.forward ){ if ( !data.forward ){
continue; continue;
} }
@ -594,7 +590,7 @@ private:
std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges; std::vector< _ContractorEdge >& insertedEdges = data->insertedEdges;
for ( _DynamicGraph::EdgeIterator inEdge = _graph->BeginEdges( node ), endInEdges = _graph->EndEdges( node ); inEdge != endInEdges; ++inEdge ) { 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 ); const NodeID source = _graph->GetTarget( inEdge );
if ( Simulate ) { if ( Simulate ) {
assert( stats != NULL ); assert( stats != NULL );
@ -610,7 +606,7 @@ private:
unsigned numTargets = 0; unsigned numTargets = 0;
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) { if ( !outData.forward ) {
continue; continue;
} }
@ -629,7 +625,7 @@ private:
_Dijkstra( maxDistance, numTargets, 2000, data, node ); _Dijkstra( maxDistance, numTargets, 2000, data, node );
} }
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) { for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge ); const ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
if ( !outData.forward ) { if ( !outData.forward ) {
continue; continue;
} }
@ -645,7 +641,7 @@ private:
_ContractorEdge newEdge; _ContractorEdge newEdge;
newEdge.source = source; newEdge.source = source;
newEdge.target = target; 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 ); insertedEdges.push_back( newEdge );
std::swap( newEdge.source, newEdge.target ); std::swap( newEdge.source, newEdge.target );
newEdge.data.forward = false; newEdge.data.forward = false;
@ -738,7 +734,7 @@ private:
if ( priority > targetPriority ) if ( priority > targetPriority )
return false; return false;
//tie breaking //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; return false;
} }
neighbours.push_back( target ); neighbours.push_back( target );
@ -760,7 +756,7 @@ private:
if ( priority > targetPriority) if ( priority > targetPriority)
return false; return false;
//tie breaking //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; return false;
} }
} }
@ -784,7 +780,8 @@ private:
boost::shared_ptr<_DynamicGraph> _graph; boost::shared_ptr<_DynamicGraph> _graph;
std::vector<_DynamicGraph::InputEdge> contractedEdges; std::vector<_DynamicGraph::InputEdge> contractedEdges;
unsigned temporaryStorageSlotID; unsigned edge_storage_slot;
uint64_t temp_edge_counter;
std::vector<NodeID> oldNodeIDFromNewNodeIDMap; std::vector<NodeID> oldNodeIDFromNewNodeIDMap;
XORFastHash fastHash; XORFastHash fastHash;
}; };

View File

@ -25,7 +25,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "EdgeBasedGraphFactory.h" #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( EdgeBasedGraphFactory::EdgeBasedGraphFactory(
int number_of_nodes, int number_of_nodes,
@ -43,7 +57,8 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
std::pair<NodeID, NodeID> restriction_source = std::pair<NodeID, NodeID> restriction_source =
std::make_pair(restriction.fromNode, restriction.viaNode); std::make_pair(restriction.fromNode, restriction.viaNode);
unsigned index; 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()) { if(restriction_iter == m_restriction_map.end()) {
index = m_restriction_bucket_list.size(); index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index+1); m_restriction_bucket_list.resize(index+1);
@ -93,7 +108,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
continue; continue;
} }
edge.data.distance = (std::max)((int)import_edge.weight(), 1 ); 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.shortcut = false;
edge.data.roundabout = import_edge.isRoundabout(); edge.data.roundabout = import_edge.isRoundabout();
edge.data.ignoreInGrid = import_edge.ignoreInGrid(); edge.data.ignoreInGrid = import_edge.ignoreInGrid();
@ -131,8 +146,8 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges(
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) { void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
#ifndef NDEBUG #ifndef NDEBUG
BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){ BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX); BOOST_ASSERT(node.lat1 != INT_MAX); BOOST_ASSERT(node.lon1 != INT_MAX);
assert(node.lat2 != INT_MAX); assert(node.lon2 != INT_MAX); BOOST_ASSERT(node.lat2 != INT_MAX); BOOST_ASSERT(node.lon2 != INT_MAX);
} }
#endif #endif
nodes.swap(m_edge_based_node_list); nodes.swap(m_edge_based_node_list);
@ -143,7 +158,8 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(
const NodeID v const NodeID v
) const { ) const {
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); 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()) { if (restriction_iter != m_restriction_map.end()) {
const unsigned index = restriction_iter->second; const unsigned index = restriction_iter->second;
BOOST_FOREACH( BOOST_FOREACH(
@ -165,7 +181,8 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted(
) const { ) const {
//only add an edge if turn is not a U-turn except it is the end of dead-end street. //only add an edge if turn is not a U-turn except it is the end of dead-end street.
const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); 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()) { if (restriction_iter != m_restriction_map.end()) {
const unsigned index = restriction_iter->second; const unsigned index = restriction_iter->second;
BOOST_FOREACH( BOOST_FOREACH(
@ -199,13 +216,34 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(
m_edge_based_node_list.push_back(currentNode); 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( void EdgeBasedGraphFactory::Run(
const char * original_edge_data_filename, const char * original_edge_data_filename,
lua_State *lua_state 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"; SimpleLogger().Write() << "Identifying components of the road network";
Percent p(m_node_based_graph->GetNumberOfNodes());
unsigned skipped_turns_counter = 0; unsigned skipped_turns_counter = 0;
unsigned node_based_edge_counter = 0; unsigned node_based_edge_counter = 0;
unsigned original_edges_counter = 0; unsigned original_edges_counter = 0;
@ -221,93 +259,21 @@ void EdgeBasedGraphFactory::Run(
sizeof(unsigned) sizeof(unsigned)
); );
unsigned current_component = 0, current_component_size = 0;
//Run a BFS on the undirected graph and identify small components //Run a BFS on the undirected graph and identify small components
std::queue<std::pair<NodeID, NodeID> > bfs_queue; std::vector<unsigned> component_index_list;
std::vector<unsigned> component_index_list( std::vector<NodeID> component_index_size;
m_node_based_graph->GetNumberOfNodes(), BFSCompentExplorer( component_index_list, component_index_size);
UINT_MAX
);
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() << SimpleLogger().Write() <<
"identified: " << component_size_list.size() << " many components"; "identified: " << component_index_size.size() << " many components";
SimpleLogger().Write() << SimpleLogger().Write() <<
"generating edge-expanded nodes"; "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. //loop over all edges and generate new set of nodes.
for( for(
NodeIterator u = 0, NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
number_of_nodes = m_node_based_graph->GetNumberOfNodes(); u < end;
u < number_of_nodes;
++u ++u
) { ) {
p.printIncrement(); p.printIncrement();
@ -326,8 +292,8 @@ void EdgeBasedGraphFactory::Run(
//Note: edges that end on barrier nodes or on a turn restriction //Note: edges that end on barrier nodes or on a turn restriction
//may actually be in two distinct components. We choose the smallest //may actually be in two distinct components. We choose the smallest
const unsigned size_of_component = std::min( const unsigned size_of_component = std::min(
component_size_list[component_index_list[u]], component_index_size[component_index_list[u]],
component_size_list[component_index_list[v]] component_index_size[component_index_list[v]]
); );
InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 ); InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 );
@ -338,12 +304,11 @@ void EdgeBasedGraphFactory::Run(
SimpleLogger().Write() SimpleLogger().Write()
<< "Generated " << m_edge_based_node_list.size() << " nodes in " << << "Generated " << m_edge_based_node_list.size() << " nodes in " <<
"edge-expanded graph"; "edge-expanded graph";
SimpleLogger().Write() << SimpleLogger().Write() << "generating edge-expanded edges";
"generating edge-expanded edges";
std::vector<NodeID>().swap(component_size_list); std::vector<NodeID>().swap(component_index_size);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
0 == component_size_list.capacity(), 0 == component_index_size.capacity(),
"component size vector not deallocated" "component size vector not deallocated"
); );
std::vector<NodeID>().swap(component_index_list); std::vector<NodeID>().swap(component_index_list);
@ -359,9 +324,8 @@ void EdgeBasedGraphFactory::Run(
//linear number of turns only. //linear number of turns only.
p.reinit(m_node_based_graph->GetNumberOfNodes()); p.reinit(m_node_based_graph->GetNumberOfNodes());
for( for(
NodeIterator u = 0, NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes();
last_node = m_node_based_graph->GetNumberOfNodes(); u < end;
u < last_node;
++u ++u
) { ) {
for( for(
@ -371,9 +335,10 @@ void EdgeBasedGraphFactory::Run(
++e1 ++e1
) { ) {
++node_based_edge_counter; ++node_based_edge_counter;
NodeIterator v = m_node_based_graph->GetTarget(e1); const NodeIterator v = m_node_based_graph->GetTarget(e1);
bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v);
NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() );
for( for(
EdgeIterator e2 = m_node_based_graph->BeginEdges(v), EdgeIterator e2 = m_node_based_graph->BeginEdges(v),
last_edge_v = m_node_based_graph->EndEdges(v); last_edge_v = m_node_based_graph->EndEdges(v);
@ -390,83 +355,91 @@ void EdgeBasedGraphFactory::Run(
continue; 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;
}
}
//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)
) {
++skipped_turns_counter;
continue; continue;
} }
if( !is_barrier_node ) { //only add an edge if turn is not prohibited
//only add an edge if turn is not a U-turn except when it is const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1);
//at the end of a dead-end street const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2);
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) { BOOST_ASSERT(
continue; 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 );
unsigned distance = edge_data1.distance; // the following is the core of the loop.
if(m_traffic_lights.find(v) != m_traffic_lights.end()) { unsigned distance = edge_data1.distance;
distance += speed_profile.trafficSignalPenalty; if( m_traffic_lights.find(v) != m_traffic_lights.end() ) {
} distance += speed_profile.trafficSignalPenalty;
const unsigned penalty =
GetTurnPenalty(u, v, w, lua_state);
TurnInstruction turnInstruction = AnalyzeTurn(u, v, w);
if(turnInstruction == TurnInstructions.UTurn){
distance += speed_profile.uTurnPenalty;
}
distance += penalty;
assert(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID);
original_edge_data_vector.push_back(
OriginalEdgeData(
v,
edge_data2.nameID,
turnInstruction
)
);
++original_edges_counter;
if(original_edge_data_vector.size() > 100000) {
edge_data_file.write(
(char*)&(original_edge_data_vector[0]),
original_edge_data_vector.size()*sizeof(OriginalEdgeData)
);
original_edge_data_vector.clear();
}
m_edge_based_edge_list.push_back(
EdgeBasedEdge(
edge_data1.edgeBasedNodeID,
edge_data2.edgeBasedNodeID,
m_edge_based_edge_list.size(),
distance,
true,
false
)
);
} else {
++skipped_turns_counter;
}
} }
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 += turn_penalty;
original_edge_data_vector.push_back(
OriginalEdgeData(
v,
edge_data2.nameID,
turnInstruction
)
);
++original_edges_counter;
if(original_edge_data_vector.size() > 100000) {
FlushVectorToStream(
edge_data_file,
original_edge_data_vector
);
}
m_edge_based_edge_list.push_back(
EdgeBasedEdge(
edge_data1.edgeBasedNodeID,
edge_data2.edgeBasedNodeID,
m_edge_based_edge_list.size(),
distance,
true,
false
)
);
} }
} }
p.printIncrement(); p.printIncrement();
} }
edge_data_file.write( FlushVectorToStream( edge_data_file, original_edge_data_vector );
(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) );
edge_data_file.seekp(std::ios::beg);
edge_data_file.write(
(char*)&original_edges_counter,
sizeof(unsigned)
);
edge_data_file.close(); edge_data_file.close();
SimpleLogger().Write() << SimpleLogger().Write() <<
@ -518,11 +491,11 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
return TurnInstructions.UTurn; return TurnInstructions.UTurn;
} }
EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v); const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v);
EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w); const EdgeIterator edge2 = m_node_based_graph->FindEdge(v, w);
EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1); const EdgeData & data1 = m_node_based_graph->GetEdgeData(edge1);
EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2); const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2);
if(!data1.contraFlow && data2.contraFlow) { if(!data1.contraFlow && data2.contraFlow) {
return TurnInstructions.EnterAgainstAllowedDirection; return TurnInstructions.EnterAgainstAllowedDirection;
@ -569,10 +542,87 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(
m_node_info_list[v], m_node_info_list[v],
m_node_info_list[w] m_node_info_list[w]
); );
return TurnInstructions.GetTurnDirectionOfInstruction(angle); return TurnInstructions.GetTurnDirectionOfInstruction(angle);
} }
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const { unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
return m_node_based_graph->GetNumberOfEdges(); 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;
}
}
}

View File

@ -34,17 +34,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../DataStructures/DeallocatingVector.h" #include "../DataStructures/DeallocatingVector.h"
#include "../DataStructures/DynamicGraph.h" #include "../DataStructures/DynamicGraph.h"
#include "../DataStructures/EdgeBasedNode.h" #include "../DataStructures/EdgeBasedNode.h"
#include "../Extractor/ExtractorStructs.h"
#include "../DataStructures/HashTable.h" #include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportEdge.h" #include "../DataStructures/ImportEdge.h"
#include "../DataStructures/QueryEdge.h" #include "../DataStructures/OriginalEdgeData.h"
#include "../DataStructures/Percent.h" #include "../DataStructures/Percent.h"
#include "../DataStructures/QueryEdge.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/TurnInstructions.h" #include "../DataStructures/TurnInstructions.h"
#include "../DataStructures/Restriction.h"
#include "../Util/LuaUtil.h" #include "../Util/LuaUtil.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/foreach.hpp> #include "GeometryCompressor.h"
#include <boost/make_shared.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
@ -80,14 +82,17 @@ public:
); );
void Run(const char * originalEdgeDataFilename, lua_State *myLuaState); void Run(const char * originalEdgeDataFilename, lua_State *myLuaState);
void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges );
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes); void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
void GetOriginalEdgeData( std::vector<OriginalEdgeData> & originalEdgeData);
TurnInstruction AnalyzeTurn( TurnInstruction AnalyzeTurn(
const NodeID u, const NodeID u,
const NodeID v, const NodeID v,
const NodeID w const NodeID w
) const; ) const;
int GetTurnPenalty( int GetTurnPenalty(
const NodeID u, const NodeID u,
const NodeID v, const NodeID v,
@ -112,15 +117,6 @@ private:
bool contraFlow:1; bool contraFlow:1;
}; };
struct _EdgeBasedEdgeData {
int distance;
unsigned via;
unsigned nameID;
bool forward;
bool backward;
TurnInstruction turnInstruction;
};
unsigned m_turn_restrictions_count; unsigned m_turn_restrictions_count;
typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph; typedef DynamicGraph<NodeBasedEdgeData> NodeBasedDynamicGraph;
@ -144,7 +140,6 @@ private:
RestrictionMap m_restriction_map; RestrictionMap m_restriction_map;
NodeID CheckForEmanatingIsOnlyTurn( NodeID CheckForEmanatingIsOnlyTurn(
const NodeID u, const NodeID u,
const NodeID v const NodeID v
@ -157,10 +152,21 @@ private:
) const; ) const;
void InsertEdgeBasedNode( void InsertEdgeBasedNode(
NodeBasedDynamicGraph::EdgeIterator e1, NodeBasedDynamicGraph::EdgeIterator e1,
NodeBasedDynamicGraph::NodeIterator u, NodeBasedDynamicGraph::NodeIterator u,
NodeBasedDynamicGraph::NodeIterator v, NodeBasedDynamicGraph::NodeIterator v,
bool belongsToTinyComponent); bool belongsToTinyComponent
);
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_ */ #endif /* EDGEBASEDGRAPHFACTORY_H_ */

View 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) );
}

View 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

View File

@ -28,113 +28,135 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "TemporaryStorage.h" #include "TemporaryStorage.h"
TemporaryStorage::TemporaryStorage() { TemporaryStorage::TemporaryStorage() {
tempDirectory = boost::filesystem::temp_directory_path(); temp_directory = boost::filesystem::temp_directory_path();
} }
TemporaryStorage & TemporaryStorage::GetInstance(){ TemporaryStorage & TemporaryStorage::GetInstance(){
static TemporaryStorage runningInstance; static TemporaryStorage static_instance;
return runningInstance; return static_instance;
} }
TemporaryStorage::~TemporaryStorage() { TemporaryStorage::~TemporaryStorage() {
removeAll(); RemoveAll();
} }
void TemporaryStorage::removeAll() { void TemporaryStorage::RemoveAll() {
boost::mutex::scoped_lock lock(mutex); boost::mutex::scoped_lock lock(mutex);
for(unsigned slot_id = 0; slot_id < vectorOfStreamDatas.size(); ++slot_id) { for(unsigned slot_id = 0; slot_id < stream_data_list.size(); ++slot_id) {
deallocateSlot(slot_id); DeallocateSlot(slot_id);
} }
vectorOfStreamDatas.clear(); stream_data_list.clear();
} }
int TemporaryStorage::allocateSlot() { int TemporaryStorage::AllocateSlot() {
boost::mutex::scoped_lock lock(mutex); boost::mutex::scoped_lock lock(mutex);
try { try {
vectorOfStreamDatas.push_back(StreamData()); stream_data_list.push_back(StreamData());
//SimpleLogger().Write() << "created new temporary file: " << vectorOfStreamDatas.back().pathToTemporaryFile;
} catch(boost::filesystem::filesystem_error & e) { } catch(boost::filesystem::filesystem_error & e) {
abort(e); Abort(e);
} }
return vectorOfStreamDatas.size() - 1; CheckIfTemporaryDeviceFull();
return stream_data_list.size() - 1;
} }
void TemporaryStorage::deallocateSlot(int slotID) { void TemporaryStorage::DeallocateSlot(const int slot_id) {
try { try {
StreamData & data = vectorOfStreamDatas[slotID]; StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex); boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(!boost::filesystem::exists(data.pathToTemporaryFile)) { if(!boost::filesystem::exists(data.temp_path)) {
return; return;
} }
if(data.streamToTemporaryFile->is_open()) { if(data.temp_file->is_open()) {
data.streamToTemporaryFile->close(); data.temp_file->close();
} }
boost::filesystem::remove(data.pathToTemporaryFile); boost::filesystem::remove(data.temp_path);
} catch(boost::filesystem::filesystem_error & e) { } 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 { 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::mutex::scoped_lock lock(*data.readWriteMutex);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
data.writeMode, data.write_mode,
"Writing after first read is not allowed" "Writing after first read is not allowed"
); );
data.streamToTemporaryFile->write(pointer, size); if( 1073741824 < data.buffer.size() ) {
} catch(boost::filesystem::filesystem_error & e) { data.temp_file->write(&data.buffer[0], data.buffer.size());
abort(e); // data.temp_file->write(pointer, size);
} data.buffer.clear();
} CheckIfTemporaryDeviceFull();
void TemporaryStorage::readFromSlot(int slotID, char * pointer, std::streamsize size) {
try {
StreamData & data = vectorOfStreamDatas[slotID];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
if(data.writeMode) {
data.writeMode = false;
data.streamToTemporaryFile->seekg(0, data.streamToTemporaryFile->beg);
} }
data.streamToTemporaryFile->read(pointer, size); data.buffer.insert(data.buffer.end(), pointer, pointer+size);
} catch(boost::filesystem::filesystem_error & e) { } catch(boost::filesystem::filesystem_error & e) {
abort(e); Abort(e);
} }
} }
void TemporaryStorage::ReadFromSlot(
unsigned TemporaryStorage::getFreeBytesOnTemporaryDevice() { const int slot_id,
boost::filesystem::space_info tempSpaceInfo; char * pointer,
const std::size_t size
) {
try { try {
tempSpaceInfo = boost::filesystem::space(tempDirectory); StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex);
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() );
}
BOOST_ASSERT( !data.write_mode );
data.temp_file->read(pointer, size);
} catch(boost::filesystem::filesystem_error & e) { } catch(boost::filesystem::filesystem_error & e) {
abort(e); Abort(e);
} }
return tempSpaceInfo.available;
} }
boost::filesystem::fstream::pos_type TemporaryStorage::tell(int slotID) { uint64_t TemporaryStorage::GetFreeBytesOnTemporaryDevice() {
uint64_t value = -1;
try {
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);
}
return value;
}
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; boost::filesystem::fstream::pos_type position;
try { try {
StreamData & data = vectorOfStreamDatas[slotID]; StreamData & data = stream_data_list[slot_id];
boost::mutex::scoped_lock lock(*data.readWriteMutex); boost::mutex::scoped_lock lock(*data.readWriteMutex);
position = data.streamToTemporaryFile->tellp(); position = data.temp_file->tellp();
} catch(boost::filesystem::filesystem_error & e) { } catch(boost::filesystem::filesystem_error & e) {
abort(e); Abort(e);
} }
return position; return position;
} }
void TemporaryStorage::abort(boost::filesystem::filesystem_error& ) { void TemporaryStorage::Abort(const boost::filesystem::filesystem_error& e) {
removeAll(); RemoveAll();
} throw OSRMException(e.what());
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);
}
} }

View File

@ -28,46 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef TEMPORARYSTORAGE_H_ #ifndef TEMPORARYSTORAGE_H_
#define TEMPORARYSTORAGE_H_ #define TEMPORARYSTORAGE_H_
#include <vector> #include "../Util/BoostFileSystemFix.h"
#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/OSRMException.h" #include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.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 #include <vector>
#warning Boost Installation with Filesystem3 missing, activating workaround #include <fstream>
#include <cstdio>
namespace boost {
namespace filesystem {
inline path temp_directory_path() {
char * buffer;
buffer = tmpnam (NULL);
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. * This class implements a singleton file storage for temporary data.
* temporary slots can be accessed by other objects through an int * temporary slots can be accessed by other objects through an int
@ -77,49 +54,65 @@ inline path unique_path(const path&) {
* -> Data is written in first phase and reread in second. * -> 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-%%%%-%%%%-%%%%"); static std::string TemporaryFilePattern("OSRM-%%%%-%%%%-%%%%");
class TemporaryStorage { class TemporaryStorage {
public: public:
static TemporaryStorage & GetInstance(); static TemporaryStorage & GetInstance();
virtual ~TemporaryStorage(); virtual ~TemporaryStorage();
int allocateSlot(); int AllocateSlot();
void deallocateSlot(int slotID); void DeallocateSlot(const int slot_id);
void writeToSlot(int slotID, char * pointer, std::streamsize size); void WriteToSlot(const int slot_id, char * pointer, const std::size_t size);
void readFromSlot(int slotID, char * pointer, std::streamsize size); void ReadFromSlot(const int slot_id, char * pointer, const std::size_t size);
//returns the number of free bytes //returns the number of free bytes
unsigned getFreeBytesOnTemporaryDevice(); uint64_t GetFreeBytesOnTemporaryDevice();
boost::filesystem::fstream::pos_type tell(int slotID); boost::filesystem::fstream::pos_type Tell(const int slot_id);
void seek(int slotID, boost::filesystem::fstream::pos_type); void RemoveAll();
void removeAll();
private: private:
TemporaryStorage(); TemporaryStorage();
TemporaryStorage(TemporaryStorage const &){}; TemporaryStorage(TemporaryStorage const &){};
TemporaryStorage& operator=(TemporaryStorage const &) {
TemporaryStorage & operator=(TemporaryStorage const &) {
return *this; return *this;
} }
void abort(boost::filesystem::filesystem_error& e);
void Abort(const boost::filesystem::filesystem_error& e);
void CheckIfTemporaryDeviceFull();
struct StreamData { struct StreamData {
bool writeMode; bool write_mode;
boost::filesystem::path pathToTemporaryFile; boost::filesystem::path temp_path;
boost::shared_ptr<boost::filesystem::fstream> streamToTemporaryFile; boost::shared_ptr<boost::filesystem::fstream> temp_file;
boost::shared_ptr<boost::mutex> readWriteMutex; boost::shared_ptr<boost::mutex> readWriteMutex;
std::vector<char> buffer;
StreamData() : StreamData() :
writeMode(true), write_mode(true),
pathToTemporaryFile (boost::filesystem::unique_path(tempDirectory.append(TemporaryFilePattern.begin(), TemporaryFilePattern.end()))), temp_path(
streamToTemporaryFile(new boost::filesystem::fstream(pathToTemporaryFile, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary)), boost::filesystem::unique_path(
readWriteMutex(new boost::mutex) 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"); throw OSRMException("temporary file could not be created");
} }
} }
}; };
//vector of file streams that is used to store temporary data //vector of file streams that is used to store temporary data
std::vector<StreamData> vectorOfStreamDatas;
boost::mutex mutex; boost::mutex mutex;
std::vector<StreamData> stream_data_list;
}; };
#endif /* TEMPORARYSTORAGE_H_ */ #endif /* TEMPORARYSTORAGE_H_ */

View File

@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef BINARYHEAP_H_INCLUDED #ifndef BINARY_HEAP_H
#define BINARYHEAP_H_INCLUDED #define BINARY_HEAP_H
//Not compatible with non contiguous node ids //Not compatible with non contiguous node ids
@ -82,6 +82,9 @@ private:
template< typename NodeID, typename Key > template< typename NodeID, typename Key >
class UnorderedMapStorage { class UnorderedMapStorage {
typedef boost::unordered_map<NodeID, Key> UnorderedMapType;
typedef typename UnorderedMapType::iterator UnorderedMapIterator;
typedef typename UnorderedMapType::const_iterator UnorderedMapConstIterator;
public: public:
UnorderedMapStorage( size_t ) { UnorderedMapStorage( size_t ) {
@ -89,8 +92,8 @@ public:
nodes.rehash(1000); nodes.rehash(1000);
} }
Key &operator[]( const NodeID node ) { Key & operator[]( const NodeID node ) {
return nodes[node]; return nodes[node];
} }
void Clear() { void Clear() {
@ -101,13 +104,13 @@ private:
boost::unordered_map< NodeID, Key > nodes; boost::unordered_map< NodeID, Key > nodes;
}; };
template<typename NodeID = unsigned> template<
struct _SimpleHeapData { typename NodeID,
NodeID parent; typename Key,
_SimpleHeapData( NodeID p ) : parent(p) { } 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 { class BinaryHeap {
private: private:
BinaryHeap( const BinaryHeap& right ); BinaryHeap( const BinaryHeap& right );
@ -117,7 +120,9 @@ public:
typedef Data DataType; typedef Data DataType;
BinaryHeap( size_t maxID ) BinaryHeap( size_t maxID )
: nodeIndex( maxID ) { :
nodeIndex( maxID )
{
Clear(); Clear();
} }
@ -210,11 +215,13 @@ public:
private: private:
class HeapNode { class HeapNode {
public: public:
HeapNode() {
}
HeapNode( NodeID n, Key k, Weight w, Data d ) HeapNode( NodeID n, Key k, Weight w, Data d )
: node( n ), key( k ), weight( w ), data( d ) { :
} node(n),
key(k),
weight(w),
data(d)
{ }
NodeID node; NodeID node;
Key key; Key key;
@ -234,14 +241,17 @@ private:
const Key droppingIndex = heap[key].index; const Key droppingIndex = heap[key].index;
const Weight weight = heap[key].weight; const Weight weight = heap[key].weight;
Key nextKey = key << 1; Key nextKey = key << 1;
while ( nextKey < static_cast<Key>( heap.size() ) ) { while( nextKey < static_cast<Key>( heap.size() ) ){
const Key nextKeyOther = nextKey + 1; const Key nextKeyOther = nextKey + 1;
if ( ( 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; nextKey = nextKeyOther;
}
if ( weight <= heap[nextKey].weight ) if ( weight <= heap[nextKey].weight ){
break; break;
}
heap[key] = heap[nextKey]; heap[key] = heap[nextKey];
insertedNodes[heap[key].index].key = key; insertedNodes[heap[key].index].key = key;
key = nextKey; key = nextKey;
@ -277,4 +287,4 @@ private:
} }
}; };
#endif //#ifndef BINARYHEAP_H_INCLUDED #endif //BINARY_HEAP_H

View File

@ -25,55 +25,51 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef FIXED_POINT_COORDINATE_H_ #include <osrm/Coordinate.h>
#define FIXED_POINT_COORDINATE_H_
#include "../DataStructures/MercatorUtil.h"
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <cmath> #include <cmath>
#include <climits> #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 { void FixedPointCoordinate::Reset() {
int lat; lat = INT_MIN;
int lon; lon = INT_MIN;
FixedPointCoordinate () : lat(INT_MIN), lon(INT_MIN) {} }
explicit FixedPointCoordinate (int lat, int lon) : lat(lat) , lon(lon) {} bool FixedPointCoordinate::isSet() const {
return (INT_MIN != lat) && (INT_MIN != lon);
void Reset() { }
lat = INT_MIN; bool FixedPointCoordinate::isValid() const {
lon = INT_MIN; if(
lat > 90*COORDINATE_PRECISION ||
lat < -90*COORDINATE_PRECISION ||
lon > 180*COORDINATE_PRECISION ||
lon < -180*COORDINATE_PRECISION
) {
return false;
} }
bool isSet() const { return true;
return (INT_MIN != lat) && (INT_MIN != lon); }
} bool FixedPointCoordinate::operator==(const FixedPointCoordinate & other) const {
inline bool isValid() const { return lat == other.lat && lon == other.lon;
if(
lat > 90*COORDINATE_PRECISION ||
lat < -90*COORDINATE_PRECISION ||
lon > 180*COORDINATE_PRECISION ||
lon < -180*COORDINATE_PRECISION
) {
return false;
}
return true;
}
bool 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(lat1 != INT_MIN);
BOOST_ASSERT(lon1 != INT_MIN); BOOST_ASSERT(lon1 != INT_MIN);
BOOST_ASSERT(lat2 != 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 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)); 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) //earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
//The IUGG value for the equatorial radius of the Earth is 6378.137 km (3963.19 mile) //The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
const double earth=6372797.560856;//I am doing miles, just change this to radius in kilometers to get distances in km const double earth=6372797.560856;
double distance=earth*cHarv; double distance=earth*cHarv;
return distance; 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 ); 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.lat != INT_MIN);
BOOST_ASSERT(c1.lon != INT_MIN); BOOST_ASSERT(c1.lon != INT_MIN);
BOOST_ASSERT(c2.lat != INT_MIN); BOOST_ASSERT(c2.lat != INT_MIN);
@ -123,48 +125,38 @@ inline double ApproximateEuclideanDistance(const FixedPointCoordinate &c1, const
return d; return d;
} }
static inline void convertInternalLatLonToString(const int value, std::string & output) { void FixedPointCoordinate::convertInternalLatLonToString(
const int value,
std::string & output
) {
char buffer[100]; char buffer[100];
buffer[11] = 0; // zero termination buffer[11] = 0; // zero termination
char* string = printInt< 11, 6 >( buffer, value ); char* string = printInt< 11, 6 >( buffer, value );
output = string; output = string;
} }
static inline void convertInternalCoordinateToString(const FixedPointCoordinate & coord, std::string & output) { void FixedPointCoordinate::convertInternalCoordinateToString(
std::string tmp; const FixedPointCoordinate & coord,
convertInternalLatLonToString(coord.lon, tmp); std::string & output
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lat, tmp);
output += tmp;
output += " ";
}
static inline void convertInternalReversedCoordinateToString(const FixedPointCoordinate & coord, std::string & output) {
std::string tmp;
convertInternalLatLonToString(coord.lat, tmp);
output = tmp;
output += ",";
convertInternalLatLonToString(coord.lon, tmp);
output += tmp;
output += " ";
}
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
template<class CoordinateT>
static inline double GetAngleBetweenThreeFixedPointCoordinates (
const CoordinateT & A,
const CoordinateT & C,
const CoordinateT & B
) { ) {
const double v1x = (A.lon - C.lon)/COORDINATE_PRECISION; std::string tmp;
const double v1y = lat2y(A.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION); tmp.reserve(23);
const double v2x = (B.lon - C.lon)/COORDINATE_PRECISION; convertInternalLatLonToString(coord.lon, tmp);
const double v2y = lat2y(B.lat/COORDINATE_PRECISION) - lat2y(C.lat/COORDINATE_PRECISION); output = tmp;
output += ",";
double angle = (atan2(v2y,v2x) - atan2(v1y,v1x) )*180/M_PI; convertInternalLatLonToString(coord.lat, tmp);
while(angle < 0) output += tmp;
angle += 360; }
return angle;
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_ */

View File

@ -41,8 +41,8 @@ template< typename EdgeDataT>
class DynamicGraph { class DynamicGraph {
public: public:
typedef EdgeDataT EdgeData; typedef EdgeDataT EdgeData;
typedef uint32_t NodeIterator; typedef unsigned NodeIterator;
typedef uint32_t EdgeIterator; typedef unsigned EdgeIterator;
class InputEdge { class InputEdge {
public: public:
@ -101,15 +101,15 @@ class DynamicGraph {
~DynamicGraph(){ } ~DynamicGraph(){ }
uint32_t GetNumberOfNodes() const { unsigned GetNumberOfNodes() const {
return m_numNodes; return m_numNodes;
} }
uint32_t GetNumberOfEdges() const { unsigned GetNumberOfEdges() const {
return m_numEdges; return m_numEdges;
} }
uint32_t GetOutDegree( const NodeIterator n ) const { unsigned GetOutDegree( const NodeIterator n ) const {
return m_nodes[n].edges; return m_nodes[n].edges;
} }
@ -117,6 +117,10 @@ class DynamicGraph {
return NodeIterator( m_edges[e].target ); return NodeIterator( m_edges[e].target );
} }
void SetTarget( const EdgeIterator e, const NodeIterator n ) {
m_edges[e].target = n;
}
EdgeDataT &GetEdgeData( const EdgeIterator e ) { EdgeDataT &GetEdgeData( const EdgeIterator e ) {
return m_edges[e].data; return m_edges[e].data;
} }
@ -143,7 +147,7 @@ class DynamicGraph {
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges]; m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
} else { } else {
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size(); EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
uint32_t newSize = node.edges * 1.1 + 2; unsigned newSize = node.edges * 1.1 + 2;
EdgeIterator requiredCapacity = newSize + m_edges.size(); EdgeIterator requiredCapacity = newSize + m_edges.size();
EdgeIterator oldCapacity = m_edges.capacity(); EdgeIterator oldCapacity = m_edges.capacity();
if ( requiredCapacity >= oldCapacity ) { if ( requiredCapacity >= oldCapacity ) {
@ -170,9 +174,12 @@ class DynamicGraph {
//removes an edge. Invalidates edge iterators for the source node //removes an edge. Invalidates edge iterators for the source node
void DeleteEdge( const NodeIterator source, const EdgeIterator e ) { void DeleteEdge( const NodeIterator source, const EdgeIterator e ) {
Node &node = m_nodes[source]; Node &node = m_nodes[source];
#pragma omp atomic
--m_numEdges; --m_numEdges;
--node.edges; --node.edges;
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 //swap with last edge
m_edges[e] = m_edges[last]; m_edges[e] = m_edges[last];
makeDummy( last ); makeDummy( last );
@ -222,7 +229,7 @@ class DynamicGraph {
//index of the first edge //index of the first edge
EdgeIterator firstEdge; EdgeIterator firstEdge;
//amount of edges //amount of edges
uint32_t edges; unsigned edges;
}; };
struct Edge { struct Edge {

View File

@ -1,21 +1,74 @@
#ifndef EDGE_BASED_NODE_H #ifndef EDGE_BASED_NODE_H
#define 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 { struct EdgeBasedNode {
EdgeBasedNode() : EdgeBasedNode() :
id(INT_MAX), id(INT_MAX),
lat1(INT_MAX), lat1(INT_MAX),
lat2(INT_MAX), lat2(INT_MAX),
lon1(INT_MAX), lon1(INT_MAX),
lon2(INT_MAX >> 1), lon2(INT_MAX >> 1),
belongsToTinyComponent(false), belongsToTinyComponent(false),
nameID(UINT_MAX), nameID(UINT_MAX),
weight(UINT_MAX >> 1), weight(UINT_MAX >> 1),
ignoreInGrid(false) 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 { bool operator<(const EdgeBasedNode & other) const {
return other.id < id; return other.id < id;
} }
@ -24,28 +77,100 @@ struct EdgeBasedNode {
return id == other.id; return id == other.id;
} }
// Returns the midpoint of the underlying edge.
inline FixedPointCoordinate Centroid() const { inline FixedPointCoordinate Centroid() const {
FixedPointCoordinate centroid; return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2);
//The coordinates of the midpoint are given by:
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
return centroid;
}
inline bool isIgnored() const {
return ignoreInGrid;
} }
NodeID id; NodeID id;
// The coordinates of the end-points of the underlying edge.
int lat1; int lat1;
int lat2; int lat2;
int lon1; int lon1;
int lon2:31; int lon2:31;
bool belongsToTinyComponent:1; bool belongsToTinyComponent:1;
NodeID nameID; NodeID nameID;
// The weight of the underlying edge.
unsigned weight:31; unsigned weight:31;
bool ignoreInGrid:1; 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 #endif //EDGE_BASED_NODE_H

View File

@ -25,43 +25,44 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef HASHTABLE_H_ #ifndef HASH_TABLE_H
#define HASHTABLE_H_ #define HASH_TABLE_H
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
template<typename keyT, typename valueT> template<typename KeyT, typename ValueT>
class HashTable : public boost::unordered_map<keyT, valueT> { class HashTable : public boost::unordered_map<KeyT, ValueT> {
private: private:
typedef boost::unordered_map<keyT, valueT> super; typedef boost::unordered_map<KeyT, ValueT> super;
public: public:
static ValueT default_value;
HashTable() : super() { } HashTable() : super() { }
HashTable(const unsigned size) : super(size) { } HashTable(const unsigned size) : super(size) { }
HashTable &operator=(const HashTable &other) { inline void Add( KeyT const & key, ValueT const & value) {
super::operator = (other); super::emplace(std::make_pair(key, value));
return *this;
} }
inline void Add(const keyT& key, const valueT& value){ inline const ValueT Find(KeyT const & key) const {
super::insert(std::make_pair(key, value)); typename super::const_iterator iter = super::find(key);
} if( iter == super::end() ) {
return boost::cref(default_value);
inline valueT Find(const keyT& key) const {
if(super::find(key) == super::end()) {
return valueT();
} }
return boost::ref(super::find(key)->second); return boost::cref(iter->second);
} }
inline bool Holds(const keyT& key) const { inline bool Holds( KeyT const & key) const {
if(super::find(key) == super::end()) { if( super::find(key) == super::end() ) {
return false; return false;
} }
return true; return true;
} }
}; };
#endif /* HASHTABLE_H_ */ template<typename KeyT, typename ValueT>
ValueT HashTable<KeyT, ValueT>::default_value;
#endif /* HASH_TABLE_H */

View 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;
}
}

View File

@ -28,70 +28,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef HILBERTVALUE_H_ #ifndef HILBERTVALUE_H_
#define HILBERTVALUE_H_ #define HILBERTVALUE_H_
#include "Coordinate.h" #include <osrm/Coordinate.h>
#include <boost/integer.hpp> #include <boost/integer.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
// computes a 64 bit value that corresponds to the hilbert space filling curve // computes a 64 bit value that corresponds to the hilbert space filling curve
class HilbertCode : boost::noncopyable { class HilbertCode : boost::noncopyable
{
public: public:
static uint64_t GetHilbertNumberForCoordinate( uint64_t operator()
(
const FixedPointCoordinate & current_coordinate 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);
const uint64_t result = BitInterleaving(location[0], location[1]);
return result;
}
private: private:
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) { inline uint64_t BitInterleaving( const uint32_t a, const uint32_t b) const;
uint64_t result = 0; inline void TransposeCoordinate( uint32_t * X) const;
for(int8_t index = 31; index >= 0; --index){
result |= (a >> index) & 1;
result <<= 1;
result |= (b >> index) & 1;
if(0 != index){
result <<= 1;
}
}
return result;
}
static inline void TransposeCoordinate( uint32_t * X) {
uint32_t M = 1 << (32-1), P, Q, t;
int i;
// Inverse undo
for( Q = M; Q > 1; Q >>= 1 ) {
P=Q-1;
for( i = 0; i < 2; ++i ) {
if( X[i] & Q ) {
X[0] ^= P; // invert
} else {
t = (X[0]^X[i]) & P;
X[0] ^= t;
X[i] ^= t;
}
} // exchange
}
// Gray encode
for( i = 1; i < 2; ++i ) {
X[i] ^= X[i-1];
}
t=0;
for( Q = M; Q > 1; Q >>= 1 ) {
if( X[2-1] & Q ) {
t ^= Q-1;
}
} //check if this for loop is wrong
for( i = 0; i < 2; ++i ) {
X[i] ^= t;
}
}
}; };
#endif /* HILBERTVALUE_H_ */ #endif /* HILBERTVALUE_H_ */

View 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

View File

@ -28,7 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef PHANTOMNODES_H_ #ifndef PHANTOMNODES_H_
#define PHANTOMNODES_H_ #define PHANTOMNODES_H_
#include "Coordinate.h" #include <osrm/Coordinate.h>
#include "../typedefs.h"
struct PhantomNode { struct PhantomNode {
PhantomNode() : PhantomNode() :

View File

@ -28,32 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef QUERYEDGE_H_ #ifndef QUERYEDGE_H_
#define QUERYEDGE_H_ #define QUERYEDGE_H_
#include "TurnInstructions.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <climits> #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 { struct QueryEdge {
NodeID source; NodeID source;
NodeID target; NodeID target;
struct EdgeData { struct EdgeData {
NodeID id:31; NodeID id:31;
bool shortcut:1; bool shortcut:1;
int distance:30; int distance:30;
bool forward:1; bool forward:1;
bool backward:1; bool backward:1;
} data; } data;
bool operator<( const QueryEdge& right ) const { bool operator<( const QueryEdge& right ) const {
@ -64,9 +51,14 @@ struct QueryEdge {
} }
bool operator== ( const QueryEdge& right ) const { bool operator== ( const QueryEdge& right ) const {
return ( source == right.source && target == right.target && data.distance == right.data.distance && return (
data.shortcut == right.data.shortcut && data.forward == right.data.forward && data.backward == right.data.backward source == right.source &&
&& data.id == right.data.id 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
); );
} }
}; };

View File

@ -28,9 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _NODE_COORDS_H #ifndef _NODE_COORDS_H
#define _NODE_COORDS_H #define _NODE_COORDS_H
#include "Coordinate.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <cstddef> #include <cstddef>

View File

@ -28,29 +28,53 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef RAWROUTEDATA_H_ #ifndef RAWROUTEDATA_H_
#define RAWROUTEDATA_H_ #define RAWROUTEDATA_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <limits>
#include <vector> #include <vector>
struct _PathData { struct PathData {
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { } 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; NodeID node;
unsigned nameID; unsigned name_id;
unsigned durationOfSegment; unsigned durationOfSegment;
short turnInstruction; short turnInstruction;
}; };
struct RawRouteData { struct RawRouteData {
std::vector< _PathData > computedShortestPath; std::vector< std::vector<PathData> > unpacked_path_segments;
std::vector< _PathData > computedAlternativePath; std::vector< PathData > unpacked_alternative;
std::vector< PhantomNodes > segmentEndCoordinates; std::vector< PhantomNodes > segmentEndCoordinates;
std::vector< FixedPointCoordinate > rawViaNodeCoordinates; std::vector< FixedPointCoordinate > rawViaNodeCoordinates;
unsigned checkSum; unsigned checkSum;
int lengthOfShortestPath; int lengthOfShortestPath;
int lengthOfAlternativePath; 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_ */ #endif /* RAWROUTEDATA_H_ */

View File

@ -105,13 +105,16 @@ struct InputRestrictionContainer {
return InputRestrictionContainer(0, 0, 0, 0); return InputRestrictionContainer(0, 0, 0, 0);
} }
static InputRestrictionContainer max_value() { 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 : struct CmpRestrictionContainerByFrom {
public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool>
{
typedef InputRestrictionContainer value_type; typedef InputRestrictionContainer value_type;
inline bool operator()( inline bool operator()(
const InputRestrictionContainer & a, const InputRestrictionContainer & a,
@ -127,9 +130,9 @@ struct CmpRestrictionContainerByFrom :
} }
}; };
struct CmpRestrictionContainerByTo: public std::binary_function<InputRestrictionContainer, InputRestrictionContainer, bool> { struct CmpRestrictionContainerByTo {
typedef InputRestrictionContainer value_type; typedef InputRestrictionContainer value_type;
inline bool operator ()( inline bool operator()(
const InputRestrictionContainer & a, const InputRestrictionContainer & a,
const InputRestrictionContainer & b const InputRestrictionContainer & b
) const { ) const {

View File

@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SEARCHENGINE_H #ifndef SEARCHENGINE_H
#define SEARCHENGINE_H #define SEARCHENGINE_H
#include "Coordinate.h"
#include "SearchEngineData.h" #include "SearchEngineData.h"
#include "PhantomNodes.h" #include "PhantomNodes.h"
#include "QueryEdge.h" #include "QueryEdge.h"
@ -38,6 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <climits> #include <climits>

View File

@ -27,41 +27,65 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SearchEngineData.h" #include "SearchEngineData.h"
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes) { void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(const unsigned number_of_nodes)
if(!forwardHeap.get()) { {
forwardHeap.reset(new QueryHeap(number_of_nodes)); if (forwardHeap.get())
} else { {
forwardHeap->Clear(); forwardHeap->Clear();
} }
if(!backwardHeap.get()) { else
backwardHeap.reset(new QueryHeap(number_of_nodes)); {
} else { forwardHeap.reset(new QueryHeap(number_of_nodes));
}
if (backwardHeap.get())
{
backwardHeap->Clear(); backwardHeap->Clear();
} }
else
{
backwardHeap.reset(new QueryHeap(number_of_nodes));
}
} }
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes) { void SearchEngineData::InitializeOrClearSecondThreadLocalStorage(const unsigned number_of_nodes)
if(!forwardHeap2.get()) { {
forwardHeap2.reset(new QueryHeap(number_of_nodes)); if (forwardHeap2.get())
} else { {
forwardHeap2->Clear(); forwardHeap2->Clear();
} }
if(!backwardHeap2.get()) { else
backwardHeap2.reset(new QueryHeap(number_of_nodes)); {
} else { forwardHeap2.reset(new QueryHeap(number_of_nodes));
}
if (backwardHeap2.get())
{
backwardHeap2->Clear(); backwardHeap2->Clear();
} }
else
{
backwardHeap2.reset(new QueryHeap(number_of_nodes));
}
} }
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes) { void SearchEngineData::InitializeOrClearThirdThreadLocalStorage(const unsigned number_of_nodes)
if(!forwardHeap3.get()) { {
forwardHeap3.reset(new QueryHeap(number_of_nodes)); if (forwardHeap3.get())
} else { {
forwardHeap3->Clear(); forwardHeap3->Clear();
} }
if(!backwardHeap3.get()) { else
backwardHeap3.reset(new QueryHeap(number_of_nodes)); {
} else { forwardHeap3.reset(new QueryHeap(number_of_nodes));
}
if (backwardHeap3.get())
{
backwardHeap3->Clear(); backwardHeap3->Clear();
} }
else
{
backwardHeap3.reset(new QueryHeap(number_of_nodes));
}
} }

View File

@ -28,24 +28,54 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SEGMENTINFORMATION_H_ #ifndef SEGMENTINFORMATION_H_
#define SEGMENTINFORMATION_H_ #define SEGMENTINFORMATION_H_
#include "Coordinate.h"
#include "TurnInstructions.h" #include "TurnInstructions.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <climits> #include <osrm/Coordinate.h>
// Struct fits everything in one cache line
struct SegmentInformation { struct SegmentInformation {
FixedPointCoordinate location; FixedPointCoordinate location;
NodeID nameID; NodeID name_id;
double length;
unsigned duration; unsigned duration;
double bearing; double length;
TurnInstruction turnInstruction; short bearing; //more than enough [0..3600] fits into 12 bits
TurnInstruction turn_instruction;
bool necessary; 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) {} explicit SegmentInformation(
SegmentInformation(const FixedPointCoordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) : const FixedPointCoordinate & location,
location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {} 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_ */ #endif /* SEGMENTINFORMATION_H_ */

View File

@ -28,19 +28,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef STATICRTREE_H_ #ifndef STATICRTREE_H_
#define STATICRTREE_H_ #define STATICRTREE_H_
#include "Coordinate.h"
#include "DeallocatingVector.h" #include "DeallocatingVector.h"
#include "HilbertValue.h" #include "HilbertValue.h"
#include "MercatorUtil.h"
#include "PhantomNodes.h" #include "PhantomNodes.h"
#include "SharedMemoryFactory.h" #include "SharedMemoryFactory.h"
#include "SharedMemoryVectorWrapper.h" #include "SharedMemoryVectorWrapper.h"
#include "../Util/MercatorUtil.h"
#include "../Util/OSRMException.h" #include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../Util/TimingUtil.h" #include "../Util/TimingUtil.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
@ -124,10 +125,10 @@ public:
FixedPointCoordinate lower_left (other.min_lat, other.min_lon); FixedPointCoordinate lower_left (other.min_lat, other.min_lon);
return ( return (
Contains(upper_left) Contains(upper_left ) ||
|| Contains(upper_right) Contains(upper_right) ||
|| Contains(lower_right) Contains(lower_right) ||
|| Contains(lower_left) Contains(lower_left )
); );
} }
@ -140,7 +141,7 @@ public:
double min_dist = std::numeric_limits<double>::max(); double min_dist = std::numeric_limits<double>::max();
min_dist = std::min( min_dist = std::min(
min_dist, min_dist,
ApproximateDistance( FixedPointCoordinate::ApproximateDistance(
location.lat, location.lat,
location.lon, location.lon,
max_lat, max_lat,
@ -149,7 +150,7 @@ public:
); );
min_dist = std::min( min_dist = std::min(
min_dist, min_dist,
ApproximateDistance( FixedPointCoordinate::ApproximateDistance(
location.lat, location.lat,
location.lon, location.lon,
max_lat, max_lat,
@ -158,7 +159,7 @@ public:
); );
min_dist = std::min( min_dist = std::min(
min_dist, min_dist,
ApproximateDistance( FixedPointCoordinate::ApproximateDistance(
location.lat, location.lat,
location.lon, location.lon,
min_lat, min_lat,
@ -167,7 +168,7 @@ public:
); );
min_dist = std::min( min_dist = std::min(
min_dist, min_dist,
ApproximateDistance( FixedPointCoordinate::ApproximateDistance(
location.lat, location.lat,
location.lon, location.lon,
min_lat, min_lat,
@ -188,32 +189,32 @@ public:
min_max_dist = std::min( min_max_dist = std::min(
min_max_dist, min_max_dist,
std::max( std::max(
ApproximateDistance(location, upper_left ), FixedPointCoordinate::ApproximateDistance(location, upper_left ),
ApproximateDistance(location, upper_right) FixedPointCoordinate::ApproximateDistance(location, upper_right)
) )
); );
min_max_dist = std::min( min_max_dist = std::min(
min_max_dist, min_max_dist,
std::max( std::max(
ApproximateDistance(location, upper_right), FixedPointCoordinate::ApproximateDistance(location, upper_right),
ApproximateDistance(location, lower_right) FixedPointCoordinate::ApproximateDistance(location, lower_right)
) )
); );
min_max_dist = std::min( min_max_dist = std::min(
min_max_dist, min_max_dist,
std::max( std::max(
ApproximateDistance(location, lower_right), FixedPointCoordinate::ApproximateDistance(location, lower_right),
ApproximateDistance(location, lower_left ) FixedPointCoordinate::ApproximateDistance(location, lower_left )
) )
); );
min_max_dist = std::min( min_max_dist = std::min(
min_max_dist, min_max_dist,
std::max( std::max(
ApproximateDistance(location, lower_left ), FixedPointCoordinate::ApproximateDistance(location, lower_left ),
ApproximateDistance(location, upper_left ) FixedPointCoordinate::ApproximateDistance(location, upper_left )
) )
); );
return min_max_dist; return min_max_dist;
@ -307,6 +308,8 @@ public:
double time1 = get_timestamp(); double time1 = get_timestamp();
std::vector<WrappedInputElement> input_wrapper_vector(m_element_count); std::vector<WrappedInputElement> input_wrapper_vector(m_element_count);
HilbertCode get_hilbert_number;
//generate auxiliary vector of hilbert-values //generate auxiliary vector of hilbert-values
#pragma omp parallel for schedule(guided) #pragma omp parallel for schedule(guided)
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) { for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
@ -316,10 +319,10 @@ public:
FixedPointCoordinate current_centroid = current_element.Centroid(); FixedPointCoordinate current_centroid = current_element.Centroid();
current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION); 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; input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
} }
//open leaf file //open leaf file
boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary); boost::filesystem::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t)); leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
@ -334,6 +337,7 @@ public:
LeafNode current_leaf; LeafNode current_leaf;
TreeNode current_node; 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) { for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
if(m_element_count > (processed_objects_count + current_element_index)) { if(m_element_count > (processed_objects_count + current_element_index)) {
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index; uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
@ -391,6 +395,7 @@ public:
//reverse and renumber tree to have root at index 0 //reverse and renumber tree to have root at index 0
std::reverse(m_search_tree.begin(), m_search_tree.end()); std::reverse(m_search_tree.begin(), m_search_tree.end());
#pragma omp parallel for schedule(guided) #pragma omp parallel for schedule(guided)
for(uint32_t i = 0; i < m_search_tree.size(); ++i) { for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
TreeNode & current_tree_node = m_search_tree[i]; TreeNode & current_tree_node = m_search_tree[i];
@ -435,7 +440,7 @@ public:
uint32_t tree_size = 0; uint32_t tree_size = 0;
tree_node_file.read((char*)&tree_size, sizeof(uint32_t)); tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
//SimpleLogger().Write() << "reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes";
m_search_tree.resize(tree_size); m_search_tree.resize(tree_size);
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size); tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
tree_node_file.close(); tree_node_file.close();
@ -526,12 +531,10 @@ public:
} }
double current_ratio = 0.; double current_ratio = 0.;
double current_perpendicular_distance = ComputePerpendicularDistance( double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
input_coordinate, input_coordinate,
FixedPointCoordinate(current_edge.lat1, current_edge.lon1),
FixedPointCoordinate(current_edge.lat2, current_edge.lon2),
nearest, nearest,
&current_ratio current_ratio
); );
if( if(
@ -556,7 +559,7 @@ public:
} else if( } else if(
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
&& CoordinatesAreEquivalent( && EdgesAreEquivalent(
current_start_coordinate, current_start_coordinate,
FixedPointCoordinate( FixedPointCoordinate(
current_edge.lat1, current_edge.lat1,
@ -675,11 +678,8 @@ public:
) { ) {
continue; continue;
} }
if(current_edge.isIgnored()) {
continue;
}
double current_minimum_distance = ApproximateDistance( double current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
input_coordinate.lat, input_coordinate.lat,
input_coordinate.lon, input_coordinate.lon,
current_edge.lat1, current_edge.lat1,
@ -693,7 +693,7 @@ public:
found_a_nearest_edge = true; found_a_nearest_edge = true;
} }
current_minimum_distance = ApproximateDistance( current_minimum_distance = FixedPointCoordinate::ApproximateDistance(
input_coordinate.lat, input_coordinate.lat,
input_coordinate.lon, input_coordinate.lon,
current_edge.lat2, current_edge.lat2,
@ -736,7 +736,6 @@ public:
return found_a_nearest_edge; return found_a_nearest_edge;
} }
bool FindPhantomNodeForCoordinate( bool FindPhantomNodeForCoordinate(
const FixedPointCoordinate & input_coordinate, const FixedPointCoordinate & input_coordinate,
PhantomNode & result_phantom_node, PhantomNode & result_phantom_node,
@ -746,7 +745,7 @@ public:
bool ignore_tiny_components = (zoom_level <= 14); bool ignore_tiny_components = (zoom_level <= 14);
DataT nearest_edge; DataT nearest_edge;
uint32_t io_count = 0; // uint32_t io_count = 0;
uint32_t explored_tree_nodes_count = 0; uint32_t explored_tree_nodes_count = 0;
//SimpleLogger().Write() << "searching for coordinate " << input_coordinate; //SimpleLogger().Write() << "searching for coordinate " << input_coordinate;
double min_dist = std::numeric_limits<double>::max(); double min_dist = std::numeric_limits<double>::max();
@ -758,15 +757,14 @@ public:
//initialize queue with root element //initialize queue with root element
std::priority_queue<QueryCandidate> traversal_queue; std::priority_queue<QueryCandidate> traversal_queue;
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate); double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
traversal_queue.push( traversal_queue.push( QueryCandidate(0, current_min_dist) );
QueryCandidate(0, current_min_dist)
);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist), std::numeric_limits<double>::epsilon() > (0. - traversal_queue.top().min_dist),
"Root element in NN Search has min dist != 0." "Root element in NN Search has min dist != 0."
); );
LeafNode current_leaf_node;
while(!traversal_queue.empty()) { while(!traversal_queue.empty()) {
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop(); const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
@ -776,33 +774,29 @@ public:
if( !prune_downward && !prune_upward ) { //downward pruning if( !prune_downward && !prune_upward ) { //downward pruning
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id]; TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
if (current_tree_node.child_is_on_disk) { if (current_tree_node.child_is_on_disk) {
LeafNode current_leaf_node;
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node); LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
++io_count; // ++io_count;
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) { for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
DataT & current_edge = current_leaf_node.objects[i]; DataT & current_edge = current_leaf_node.objects[i];
if(ignore_tiny_components && current_edge.belongsToTinyComponent) { if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
continue; continue;
} }
if(current_edge.isIgnored()) {
continue;
}
double current_ratio = 0.; double current_ratio = 0.;
double current_perpendicular_distance = ComputePerpendicularDistance( double current_perpendicular_distance = current_edge.ComputePerpendicularDistance(
input_coordinate, input_coordinate,
FixedPointCoordinate(current_edge.lat1, current_edge.lon1), nearest,
FixedPointCoordinate(current_edge.lat2, current_edge.lon2), current_ratio
nearest,
&current_ratio
); );
BOOST_ASSERT( 0. <= current_perpendicular_distance );
if( if(
current_perpendicular_distance < min_dist ( current_perpendicular_distance < min_dist ) &&
&& !DoubleEpsilonCompare( !DoubleEpsilonCompare(
current_perpendicular_distance, current_perpendicular_distance,
min_dist min_dist
) )
) { //found a new minimum ) { //found a new minimum
min_dist = current_perpendicular_distance; min_dist = current_perpendicular_distance;
result_phantom_node.edgeBasedNode = current_edge.id; result_phantom_node.edgeBasedNode = current_edge.id;
@ -816,10 +810,10 @@ public:
current_end_coordinate.lon = current_edge.lon2; current_end_coordinate.lon = current_edge.lon2;
nearest_edge = current_edge; nearest_edge = current_edge;
found_a_nearest_edge = true; found_a_nearest_edge = true;
} else if( } else
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) &&
&& CoordinatesAreEquivalent( EdgesAreEquivalent(
current_start_coordinate, current_start_coordinate,
FixedPointCoordinate( FixedPointCoordinate(
current_edge.lat1, current_edge.lat1,
@ -853,10 +847,10 @@ public:
if( current_min_max_dist < min_max_dist ) { if( current_min_max_dist < min_max_dist ) {
min_max_dist = current_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; continue;
} }
if (current_min_dist > min_dist) { //upward pruning if( current_min_dist > min_dist ) { //upward pruning
continue; continue;
} }
traversal_queue.push(QueryCandidate(child_id, current_min_dist)); 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. //Hack to fix rounding errors and wandering via nodes.
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) { if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
result_phantom_node.location.lon = input_coordinate.lon; result_phantom_node.location.lon = input_coordinate.lon;
@ -884,8 +867,30 @@ public:
result_phantom_node.location.lat = input_coordinate.lat; 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: private:
@ -910,60 +915,17 @@ private:
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode)); thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
} }
inline double ComputePerpendicularDistance( inline bool EdgesAreEquivalent(
const FixedPointCoordinate& inputPoint, const FixedPointCoordinate & a,
const FixedPointCoordinate& source, const FixedPointCoordinate & b,
const FixedPointCoordinate& target, const FixedPointCoordinate & c,
FixedPointCoordinate& nearest, double *r) const { const FixedPointCoordinate & d
const double x = inputPoint.lat/COORDINATE_PRECISION; ) const {
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 {
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c); return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
} }
inline bool DoubleEpsilonCompare(const double d1, const double d2) const { inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
return (std::fabs(d1 - d2) < std::numeric_limits<double>::epsilon() ); return (std::abs(d1 - d2) < std::numeric_limits<double>::epsilon() );
} }
}; };

View File

@ -28,15 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASE_DESCRIPTOR_H_ #ifndef BASE_DESCRIPTOR_H_
#define BASE_DESCRIPTOR_H_ #define BASE_DESCRIPTOR_H_
#include "../DataStructures/HashTable.h"
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h" #include "../DataStructures/RawRouteData.h"
#include "../Server/Http/Reply.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <cmath> #include <osrm/Reply.h>
#include <cstdio>
#include <string> #include <string>
#include <vector> #include <vector>
@ -61,10 +57,10 @@ public:
//Maybe someone can explain the pure virtual destructor thing to me (dennis) //Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { } virtual ~BaseDescriptor() { }
virtual void Run( virtual void Run(
http::Reply & reply, const RawRouteData & rawRoute,
const RawRouteData &rawRoute, const PhantomNodes & phantomNodes,
PhantomNodes &phantomNodes, DataFacadeT * facade,
const DataFacadeT * facade http::Reply & reply
) = 0; ) = 0;
virtual void SetConfig(const DescriptorConfig & config) = 0; virtual void SetConfig(const DescriptorConfig & config) = 0;
}; };

View File

@ -43,13 +43,13 @@ double DescriptionFactory::GetBearing(
const FixedPointCoordinate & A, const FixedPointCoordinate & A,
const FixedPointCoordinate & B const FixedPointCoordinate & B
) const { ) 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 lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION);
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION); const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION);
const double y = sin(deltaLong) * cos(lat2); const double y = sin(delta_long) * cos(lat2);
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(deltaLong); const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
double result = RadianToDegree(atan2(y, x)); double result = RadianToDegree(atan2(y, x));
while(result < 0.) { while(result < 0.) {
result += 360.; result += 360.;
@ -60,22 +60,22 @@ double DescriptionFactory::GetBearing(
return result; return result;
} }
void DescriptionFactory::SetStartSegment(const PhantomNode & sph) { void DescriptionFactory::SetStartSegment(const PhantomNode & start) {
start_phantom = sph; start_phantom = start;
AppendSegment( AppendSegment(
sph.location, start.location,
_PathData(0, sph.nodeBasedEdgeNameID, 10, sph.weight1) PathData(0, start.nodeBasedEdgeNameID, 10, start.weight1)
); );
} }
void DescriptionFactory::SetEndSegment(const PhantomNode & tph) { void DescriptionFactory::SetEndSegment(const PhantomNode & target) {
target_phantom = tph; target_phantom = target;
pathDescription.push_back( pathDescription.push_back(
SegmentInformation( SegmentInformation(
tph.location, target.location,
tph.nodeBasedEdgeNameID, target.nodeBasedEdgeNameID,
0, 0,
tph.weight1, target.weight1,
0, 0,
true true
) )
@ -84,12 +84,23 @@ void DescriptionFactory::SetEndSegment(const PhantomNode & tph) {
void DescriptionFactory::AppendSegment( void DescriptionFactory::AppendSegment(
const FixedPointCoordinate & coordinate, const FixedPointCoordinate & coordinate,
const _PathData & data const PathData & data
) { ) {
if(1 == pathDescription.size() && pathDescription.back().location == coordinate) { if(
pathDescription.back().nameID = data.nameID; ( 1 == pathDescription.size()) &&
( pathDescription.back().location == coordinate)
) {
pathDescription.back().name_id = data.name_id;
} else { } 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); 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( void DescriptionFactory::BuildRouteSummary(
const double distance, const double distance,
const unsigned time const unsigned time

View File

@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Algorithms/DouglasPeucker.h" #include "../Algorithms/DouglasPeucker.h"
#include "../Algorithms/PolylineCompressor.h" #include "../Algorithms/PolylineCompressor.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h" #include "../DataStructures/RawRouteData.h"
#include "../DataStructures/SegmentInformation.h" #include "../DataStructures/SegmentInformation.h"
@ -38,6 +37,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../typedefs.h" #include "../typedefs.h"
#include <osrm/Coordinate.h>
#include <limits> #include <limits>
#include <vector> #include <vector>
@ -70,8 +71,8 @@ public:
) { ) {
//compute distance/duration for route summary //compute distance/duration for route summary
intToString(round(distance), lengthString); intToString(round(distance), lengthString);
int travelTime = time/10 + 1; int travel_time = time/10;
intToString(travelTime, durationString); intToString(std::max(travel_time, 1), durationString);
} }
} summary; } summary;
@ -84,34 +85,31 @@ public:
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const; double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const;
void AppendEncodedPolylineString(std::vector<std::string> &output) const; void AppendEncodedPolylineString(std::vector<std::string> &output) const;
void AppendUnencodedPolylineString(std::vector<std::string> &output) const; void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
void AppendSegment(const FixedPointCoordinate & coordinate, const _PathData & data); void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data);
void BuildRouteSummary(const double distance, const unsigned time); void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & start_phantom); void SetStartSegment(const PhantomNode & start_phantom);
void SetEndSegment(const PhantomNode & start_phantom); void SetEndSegment(const PhantomNode & start_phantom);
void AppendEncodedPolylineString( void AppendEncodedPolylineString(
const bool return_encoded, const bool return_encoded,
std::vector<std::string> & output std::vector<std::string> & output
); );
template<class DataFacadeT> template<class DataFacadeT>
void Run(const DataFacadeT * facade, const unsigned zoomLevel) { void Run(
const DataFacadeT * facade,
const unsigned zoomLevel
) {
if( pathDescription.empty() ) { if( pathDescription.empty() ) {
return; return;
} }
// unsigned entireLength = 0;
/** starts at index 1 */ /** starts at index 1 */
pathDescription[0].length = 0; pathDescription[0].length = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) { 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; // std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].name_id);
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
// std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].nameID);
// std::string string1; // std::string string1;
@ -129,8 +127,8 @@ public:
// unsigned lastTurn = 0; // unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) { // for(unsigned i = 1; i < pathDescription.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].nameID); // string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turnInstruction) { // if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) {
// if(std::string::npos != string0.find(string1+";") // if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1) // || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;") // || std::string::npos != string0.find(string1+" ;")
@ -138,24 +136,27 @@ public:
// ){ // ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1; // SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1;
// for(; lastTurn != i; ++lastTurn) // for(; lastTurn != i; ++lastTurn)
// pathDescription[lastTurn].nameID = pathDescription[i].nameID; // pathDescription[lastTurn].name_id = pathDescription[i].name_id;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn; // pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
// } else if(std::string::npos != string1.find(string0+";") // } else if(std::string::npos != string1.find(string0+";")
// || std::string::npos != string1.find(";"+string0) // || std::string::npos != string1.find(";"+string0)
// || std::string::npos != string1.find(string0+" ;") // || std::string::npos != string1.find(string0+" ;")
// || std::string::npos != string1.find("; "+string0) // || std::string::npos != string1.find("; "+string0)
// ){ // ){
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0; // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0;
// pathDescription[i].nameID = pathDescription[i-1].nameID; // pathDescription[i].name_id = pathDescription[i-1].name_id;
// pathDescription[i].turnInstruction = TurnInstructionsClass::NoTurn; // pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn;
// } // }
// } // }
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) { // if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
// lastTurn = i; // lastTurn = i;
// } // }
// string0 = string1; // string0 = string1;
// } // }
double lengthOfSegment = 0;
unsigned durationOfSegment = 0;
unsigned indexOfSegmentBegin = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) { for(unsigned i = 1; i < pathDescription.size(); ++i) {
entireLength += pathDescription[i].length; entireLength += pathDescription[i].length;
@ -165,37 +166,31 @@ public:
pathDescription[indexOfSegmentBegin].duration = durationOfSegment; pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
if(TurnInstructionsClass::NoTurn != pathDescription[i].turnInstruction) { if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) {
//SimpleLogger().Write() << "Turn after " << lengthOfSegment << "m into way with name id " << pathDescription[i].nameID; BOOST_ASSERT(pathDescription[i].necessary);
assert(pathDescription[i].necessary);
lengthOfSegment = 0; lengthOfSegment = 0;
durationOfSegment = 0; durationOfSegment = 0;
indexOfSegmentBegin = i; indexOfSegmentBegin = i;
} }
} }
// SimpleLogger().Write() << "#segs: " << pathDescription.size();
//Post-processing to remove empty or nearly empty path segments //Post-processing to remove empty or nearly empty path segments
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) { 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){ if(pathDescription.size() > 2){
pathDescription.pop_back(); pathDescription.pop_back();
pathDescription.back().necessary = true; pathDescription.back().necessary = true;
pathDescription.back().turnInstruction = TurnInstructions.NoTurn; pathDescription.back().turn_instruction = TurnInstructions.NoTurn;
target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID; target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->name_id;
// SimpleLogger().Write() << "Deleting last turn instruction";
} }
} else { } else {
pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio); pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio);
} }
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) { if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) {
//TODO: this is never called actually?
if(pathDescription.size() > 2) { if(pathDescription.size() > 2) {
pathDescription.erase(pathDescription.begin()); pathDescription.erase(pathDescription.begin());
pathDescription[0].turnInstruction = TurnInstructions.HeadOn; pathDescription[0].turn_instruction = TurnInstructions.HeadOn;
pathDescription[0].necessary = true; pathDescription[0].necessary = true;
start_phantom.nodeBasedEdgeNameID = pathDescription[0].nameID; start_phantom.nodeBasedEdgeNameID = pathDescription[0].name_id;
// SimpleLogger().Write() << "Deleting first turn instruction, ratio: " << start_phantom.ratio << ", length: " << pathDescription[0].length;
} }
} else { } else {
pathDescription[0].duration *= start_phantom.ratio; pathDescription[0].duration *= start_phantom.ratio;
@ -208,11 +203,9 @@ public:
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){ for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){
if(pathDescription[i].necessary) { if(pathDescription[i].necessary) {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location); double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location);
pathDescription[i].bearing = angle; pathDescription[i].bearing = angle*10;
} }
} }
// BuildRouteSummary(entireLength, duration);
return; return;
} }
}; };

View File

@ -44,10 +44,10 @@ public:
//TODO: reorder parameters //TODO: reorder parameters
void Run( void Run(
http::Reply & reply, const RawRouteData &raw_route,
const RawRouteData &rawRoute, const PhantomNodes &phantom_node_list,
PhantomNodes &phantomNodes, DataFacadeT * facade,
const DataFacadeT * facade http::Reply & reply
) { ) {
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content.push_back( reply.content.push_back(
@ -61,38 +61,41 @@ public:
" OpenStreetMap contributors (ODbL)</license></copyright>" " OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>"); "</metadata>");
reply.content.push_back("<rte>"); reply.content.push_back("<rte>");
bool found_route = (rawRoute.lengthOfShortestPath != INT_MAX) && bool found_route = (raw_route.lengthOfShortestPath != INT_MAX) &&
(rawRoute.computedShortestPath.size() ); (raw_route.unpacked_path_segments[0].size());
if( found_route ) { if( found_route ) {
convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantomNodes.startPhantom.location.lat, phantom_node_list.startPhantom.location.lat,
tmp tmp
); );
reply.content.push_back("<rtept lat=\"" + tmp + "\" "); reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantomNodes.startPhantom.location.lon, phantom_node_list.startPhantom.location.lon,
tmp tmp
); );
reply.content.push_back("lon=\"" + tmp + "\"></rtept>"); reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
BOOST_FOREACH( for(unsigned i=0; i < raw_route.unpacked_path_segments.size(); ++i){
const _PathData & pathData, BOOST_FOREACH(
rawRoute.computedShortestPath const PathData & pathData,
) { raw_route.unpacked_path_segments[i]
current = facade->GetCoordinateOfNode(pathData.node); ) {
current = facade->GetCoordinateOfNode(pathData.node);
convertInternalLatLonToString(current.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp);
reply.content.push_back("<rtept 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>"); reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
}
} }
convertInternalLatLonToString( // Add the via point or the end coordinate
phantomNodes.targetPhantom.location.lat, FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.targetPhantom.location.lat,
tmp tmp
); );
reply.content.push_back("<rtept lat=\"" + tmp + "\" "); reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantomNodes.targetPhantom.location.lon, phantom_node_list.targetPhantom.location.lon,
tmp tmp
); );
reply.content.push_back("lon=\"" + tmp + "\"></rtept>"); reply.content.push_back("lon=\"" + tmp + "\"></rtept>");

View File

@ -44,9 +44,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
template<class DataFacadeT> template<class DataFacadeT>
class JSONDescriptor : public BaseDescriptor<DataFacadeT> { class JSONDescriptor : public BaseDescriptor<DataFacadeT> {
private: private:
DataFacadeT * facade;
DescriptorConfig config; DescriptorConfig config;
DescriptionFactory description_factory; DescriptionFactory description_factory;
DescriptionFactory alternateDescriptionFactory; DescriptionFactory alternate_descriptionFactory;
FixedPointCoordinate current; FixedPointCoordinate current;
unsigned entered_restricted_area_count; unsigned entered_restricted_area_count;
struct RoundAbout{ struct RoundAbout{
@ -68,6 +69,7 @@ private:
int position; int position;
}; };
std::vector<Segment> shortest_path_segments, alternative_path_segments; std::vector<Segment> shortest_path_segments, alternative_path_segments;
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
struct RouteNames { struct RouteNames {
std::string shortestPathName1; std::string shortestPathName1;
@ -77,37 +79,72 @@ private:
}; };
public: 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; } void SetConfig(const DescriptorConfig & c) { config = c; }
//TODO: reorder parameters int DescribeLeg(
void Run( const std::vector<PathData> & route_leg,
http::Reply & reply, const PhantomNodes & leg_phantoms
const RawRouteData & raw_route_information,
PhantomNodes & phantom_nodes,
const DataFacadeT * facade
) { ) {
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(raw_route_information.lengthOfShortestPath != INT_MAX) { if(INT_MAX == raw_route.lengthOfShortestPath) {
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 );
}
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
} else {
//We do not need to do much, if there is no route ;-) //We do not need to do much, if there is no route ;-)
reply.content.push_back("207," reply.content.push_back(
"\"status_message\": \"Cannot find route between points\","); "207,\"status_message\": \"Cannot find route between points\"}"
);
return;
} }
description_factory.SetStartSegment(phantom_nodes.startPhantom);
reply.content.push_back("0,"
"\"status_message\": \"Found route between points\",");
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for( unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i ) {
const int added_segments = DescribeLeg(
raw_route.unpacked_path_segments[i],
raw_route.segmentEndCoordinates[i]
);
BOOST_ASSERT( 0 < added_segments );
shortest_leg_end_indices.push_back(
added_segments + shortest_leg_end_indices.back()
);
}
description_factory.SetEndSegment(phantom_nodes.targetPhantom);
description_factory.Run(facade, config.zoom_level); description_factory.Run(facade, config.zoom_level);
reply.content.push_back("\"route_geometry\": "); reply.content.push_back("\"route_geometry\": ");
if(config.geometry) { if(config.geometry) {
description_factory.AppendEncodedPolylineString( description_factory.AppendEncodedPolylineString(
@ -118,30 +155,20 @@ public:
reply.content.push_back("[]"); reply.content.push_back("[]");
} }
reply.content.push_back("," reply.content.push_back(",\"route_instructions\": [");
"\"route_instructions\": [");
entered_restricted_area_count = 0;
if(config.instructions) { if(config.instructions) {
BuildTextualDescription( BuildTextualDescription(
description_factory, description_factory,
reply, reply,
raw_route_information.lengthOfShortestPath, raw_route.lengthOfShortestPath,
facade, facade,
shortest_path_segments 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("],"); reply.content.push_back("],");
description_factory.BuildRouteSummary( description_factory.BuildRouteSummary(
description_factory.entireLength, description_factory.entireLength,
raw_route_information.lengthOfShortestPath - ( entered_restricted_area_count*TurnInstructions.AccessRestrictionPenalty) raw_route.lengthOfShortestPath
); );
reply.content.push_back("\"route_summary\":"); reply.content.push_back("\"route_summary\":");
@ -167,62 +194,67 @@ public:
//only one alternative route is computed at this time, so this is hardcoded //only one alternative route is computed at this time, so this is hardcoded
if(raw_route_information.lengthOfAlternativePath != INT_MAX) { if(raw_route.lengthOfAlternativePath != INT_MAX) {
alternateDescriptionFactory.SetStartSegment(phantom_nodes.startPhantom); alternate_descriptionFactory.SetStartSegment(phantom_nodes.startPhantom);
//Get all the coordinates for the computed route //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); 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\": ["); 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 //Generate the linestrings for each alternative
alternateDescriptionFactory.AppendEncodedPolylineString( alternate_descriptionFactory.AppendEncodedPolylineString(
config.encode_geometry, config.encode_geometry,
reply.content reply.content
); );
} }
reply.content.push_back("],"); reply.content.push_back("],");
reply.content.push_back("\"alternative_instructions\":["); reply.content.push_back("\"alternative_instructions\":[");
entered_restricted_area_count = 0; if(INT_MAX != raw_route.lengthOfAlternativePath) {
if(INT_MAX != raw_route_information.lengthOfAlternativePath) {
reply.content.push_back("["); reply.content.push_back("[");
//Generate instructions for each alternative //Generate instructions for each alternative
if(config.instructions) { if(config.instructions) {
BuildTextualDescription( BuildTextualDescription(
alternateDescriptionFactory, alternate_descriptionFactory,
reply, reply,
raw_route_information.lengthOfAlternativePath, raw_route.lengthOfAlternativePath,
facade, facade,
alternative_path_segments 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("],"); reply.content.push_back("],");
reply.content.push_back("\"alternative_summaries\":["); 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 //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("{");
reply.content.push_back("\"total_distance\":"); 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("," reply.content.push_back(","
"\"total_time\":"); "\"total_time\":");
reply.content.push_back(alternateDescriptionFactory.summary.durationString); reply.content.push_back(
alternate_descriptionFactory.summary.durationString
);
reply.content.push_back("," reply.content.push_back(","
"\"start_point\":\""); "\"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("\"," reply.content.push_back("\","
"\"end_point\":\""); "\"end_point\":\"");
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName)); reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName));
@ -231,7 +263,7 @@ public:
} }
reply.content.push_back("],"); reply.content.push_back("],");
//Get Names for both routes // //Get Names for both routes
RouteNames routeNames; RouteNames routeNames;
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames); GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
@ -249,47 +281,66 @@ public:
reply.content.push_back("],"); reply.content.push_back("],");
//list all viapoints so that the client may display it //list all viapoints so that the client may display it
reply.content.push_back("\"via_points\":["); 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); BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() );
reply.content.push_back("],");
} std::string tmp;
reply.content.push_back("["); FixedPointCoordinate::convertInternalReversedCoordinateToString(
if(raw_route_information.segmentEndCoordinates.back().startPhantom.location.isSet()) raw_route.segmentEndCoordinates.front().startPhantom.location,
convertInternalReversedCoordinateToString(raw_route_information.segmentEndCoordinates.back().targetPhantom.location, tmp); tmp
else );
convertInternalReversedCoordinateToString(raw_route_information.rawViaNodeCoordinates.back(), tmp); reply.content.push_back("[");
reply.content.push_back(tmp);
reply.content.push_back("]");
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) {
tmp.clear();
FixedPointCoordinate::convertInternalReversedCoordinateToString(
nodes.targetPhantom.location,
tmp
);
reply.content.push_back(",[");
reply.content.push_back(tmp); reply.content.push_back(tmp);
reply.content.push_back("]"); 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("],");
reply.content.push_back("\"hint_data\": {"); reply.content.push_back("\"hint_data\": {");
reply.content.push_back("\"checksum\":"); 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(tmp);
reply.content.push_back(", \"locations\": ["); reply.content.push_back(", \"locations\": [");
std::string hint; 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("\""); 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(hint);
reply.content.push_back("\", "); 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("\"");
reply.content.push_back(hint); reply.content.push_back(hint);
reply.content.push_back("\"]"); reply.content.push_back("\"]");
reply.content.push_back("},"); reply.content.push_back("}}");
reply.content.push_back("\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"");
reply.content.push_back("}");
} }
// construct routes names // 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 //TODO: reorder parameters
inline void BuildTextualDescription( inline void BuildTextualDescription(
DescriptionFactory & description_factory, DescriptionFactory & description_factory,
@ -383,11 +426,11 @@ public:
std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction; std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction;
//Fetch data from Factory and generate a string from it. //Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) { BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) {
TurnInstruction current_instruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; TurnInstruction current_instruction = segment.turn_instruction & TurnInstructions.InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turnInstruction); entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if(TurnInstructions.TurnIsNecessary( current_instruction) ) { if(TurnInstructions.TurnIsNecessary( current_instruction) ) {
if(TurnInstructions.EnterRoundAbout == current_instruction) { if(TurnInstructions.EnterRoundAbout == current_instruction) {
roundAbout.name_id = segment.nameID; roundAbout.name_id = segment.name_id;
roundAbout.start_index = prefixSumOfNecessarySegments; roundAbout.start_index = prefixSumOfNecessarySegments;
} else { } else {
if(0 != prefixSumOfNecessarySegments){ if(0 != prefixSumOfNecessarySegments){
@ -407,7 +450,7 @@ public:
} }
reply.content.push_back("\",\""); 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("\","); reply.content.push_back("\",");
intToString(segment.length, tmpDist); intToString(segment.length, tmpDist);
reply.content.push_back(tmpDist); reply.content.push_back(tmpDist);
@ -421,15 +464,16 @@ public:
intToString(segment.length, tmpLength); intToString(segment.length, tmpLength);
reply.content.push_back(tmpLength); reply.content.push_back(tmpLength);
reply.content.push_back("m\",\""); 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("\","); reply.content.push_back("\",");
intToString(round(segment.bearing), tmpBearing); intToString(bearing_value, tmpBearing);
reply.content.push_back(tmpBearing); reply.content.push_back(tmpBearing);
reply.content.push_back("]"); reply.content.push_back("]");
route_segments_list.push_back( route_segments_list.push_back(
Segment( Segment(
segment.nameID, segment.name_id,
segment.length, segment.length,
route_segments_list.size() route_segments_list.size()
) )
@ -461,6 +505,6 @@ public:
reply.content.push_back("]"); reply.content.push_back("]");
} }
} }
}; };
#endif /* JSON_DESCRIPTOR_H_ */ #endif /* JSON_DESCRIPTOR_H_ */

View File

@ -26,22 +26,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "BaseParser.h" #include "BaseParser.h"
#include "ExtractionWay.h"
#include "ScriptingEnvironment.h"
BaseParser::BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se) : #include "../DataStructures/ImportNode.h"
extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_restrictions(true) { #include "../Util/LuaUtil.h"
luaState = se.getLuaStateForThreadID(0); #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(); ReadUseRestrictionsSetting();
ReadRestrictionExceptions(); ReadRestrictionExceptions();
} }
void BaseParser::ReadUseRestrictionsSetting() { void BaseParser::ReadUseRestrictionsSetting() {
if( 0 != luaL_dostring( luaState, "return use_turn_restrictions\n") ) { if( 0 != luaL_dostring( lua_state, "return use_turn_restrictions\n") ) {
throw OSRMException( throw OSRMException("ERROR occured in scripting block");
/*lua_tostring( luaState, -1 ) + */"ERROR occured in scripting block"
);
} }
if( lua_isboolean( luaState, -1) ) { if( lua_isboolean( lua_state, -1) ) {
use_turn_restrictions = lua_toboolean(luaState, -1); use_turn_restrictions = lua_toboolean(lua_state, -1);
} }
if( use_turn_restrictions ) { if( use_turn_restrictions ) {
SimpleLogger().Write() << "Using turn restrictions"; SimpleLogger().Write() << "Using turn restrictions";
@ -51,16 +66,18 @@ void BaseParser::ReadUseRestrictionsSetting() {
} }
void BaseParser::ReadRestrictionExceptions() { void BaseParser::ReadRestrictionExceptions() {
if(lua_function_exists(luaState, "get_exceptions" )) { if(lua_function_exists(lua_state, "get_exceptions" )) {
//get list of turn restriction exceptions //get list of turn restriction exceptions
luabind::call_function<void>( luabind::call_function<void>(
luaState, lua_state,
"get_exceptions", "get_exceptions",
boost::ref(restriction_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) { BOOST_FOREACH(const std::string & str, restriction_exceptions) {
SimpleLogger().Write() << " " << str; SimpleLogger().Write() << " " << str;
} }
} else { } else {
SimpleLogger().Write() << "Found no exceptions to turn restrictions"; SimpleLogger().Write() << "Found no exceptions to turn restrictions";
@ -74,20 +91,32 @@ void BaseParser::report_errors(lua_State *L, const int status) const {
} }
} }
void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* localLuaState) { void BaseParser::ParseNodeInLua(ImportNode& n, lua_State* local_lua_state) {
luabind::call_function<void>( localLuaState, "node_function", boost::ref(n) ); luabind::call_function<void>(
local_lua_state,
"node_function",
boost::ref(n)
);
} }
void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* localLuaState) { void BaseParser::ParseWayInLua(ExtractionWay& w, lua_State* local_lua_state) {
luabind::call_function<void>( localLuaState, "way_function", boost::ref(w) ); 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: //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 // a) the list of modes in the except tag of the restriction
//b) the lua profile defines a hierachy of modes, ex: [access, vehicle, bicycle] // (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; return false;
} }
@ -95,8 +124,14 @@ bool BaseParser::ShouldIgnoreRestriction(const std::string & except_tag_string)
//only a few exceptions are actually defined. //only a few exceptions are actually defined.
std::vector<std::string> exceptions; std::vector<std::string> exceptions;
boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*")); boost::algorithm::split_regex(exceptions, except_tag_string, boost::regex("[;][ ]*"));
BOOST_FOREACH(std::string& str, exceptions) { BOOST_FOREACH(std::string& current_string, exceptions) {
if( restriction_exceptions.end() != std::find(restriction_exceptions.begin(), restriction_exceptions.end(), str) ) { 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; return true;
} }
} }

View File

@ -28,11 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASEPARSER_H_ #ifndef BASEPARSER_H_
#define BASEPARSER_H_ #define BASEPARSER_H_
#include "ExtractorCallbacks.h"
#include "ScriptingEnvironment.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
extern "C" { extern "C" {
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -40,29 +35,40 @@ extern "C" {
} }
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <string>
#include <vector>
class ExtractorCallbacks;
class ScriptingEnvironment;
struct ExtractionWay;
struct ImportNode;
class BaseParser : boost::noncopyable { class BaseParser : boost::noncopyable {
public: public:
BaseParser(ExtractorCallbacks* ec, ScriptingEnvironment& se); BaseParser(
ExtractorCallbacks * extractor_callbacks,
ScriptingEnvironment & scripting_environment
);
virtual ~BaseParser() {} virtual ~BaseParser() {}
virtual bool ReadHeader() = 0; virtual bool ReadHeader() = 0;
virtual bool Parse() = 0; virtual bool Parse() = 0;
virtual void ParseNodeInLua(ImportNode& n, lua_State* luaStateForThread); virtual void ParseNodeInLua(ImportNode & n, lua_State* thread_lua_state);
virtual void ParseWayInLua(ExtractionWay& n, lua_State* luaStateForThread); virtual void ParseWayInLua(ExtractionWay & n, lua_State* thread_lua_state);
virtual void report_errors(lua_State *L, const int status) const; virtual void report_errors(lua_State * lua_state, const int status) const;
protected: protected:
virtual void ReadUseRestrictionsSetting(); virtual void ReadUseRestrictionsSetting();
virtual void ReadRestrictionExceptions(); virtual void ReadRestrictionExceptions();
virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const; virtual bool ShouldIgnoreRestriction(
const std::string & except_tag_string
) const;
ExtractorCallbacks* extractor_callbacks; ExtractorCallbacks * extractor_callbacks;
ScriptingEnvironment& scriptingEnvironment; lua_State * lua_state;
lua_State* luaState; ScriptingEnvironment & scripting_environment;
std::vector<std::string> restriction_exceptions; std::vector<std::string> restriction_exceptions;
bool use_turn_restrictions; bool use_turn_restrictions;
}; };
#endif /* BASEPARSER_H_ */ #endif /* BASEPARSER_H_ */

View File

@ -26,6 +26,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "ExtractionContainers.h" #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( void ExtractionContainers::PrepareData(
const std::string & output_file_name, const std::string & output_file_name,
@ -304,7 +329,7 @@ void ExtractionContainers::PrepareData(
edge_iterator->targetCoord.lat = node_iterator->lat; edge_iterator->targetCoord.lat = node_iterator->lat;
edge_iterator->targetCoord.lon = node_iterator->lon; edge_iterator->targetCoord.lon = node_iterator->lon;
const double distance = ApproximateDistance( const double distance = FixedPointCoordinate::ApproximateDistance(
edge_iterator->startCoord.lat, edge_iterator->startCoord.lat,
edge_iterator->startCoord.lon, edge_iterator->startCoord.lon,
node_iterator->lat, node_iterator->lat,

View File

@ -28,17 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef EXTRACTIONCONTAINERS_H_ #ifndef EXTRACTIONCONTAINERS_H_
#define EXTRACTIONCONTAINERS_H_ #define EXTRACTIONCONTAINERS_H_
#include "InternalExtractorEdge.h"
#include "ExtractorStructs.h" #include "ExtractorStructs.h"
#include "../Util/SimpleLogger.h" #include "../DataStructures/Restriction.h"
#include "../Util/TimingUtil.h"
#include "../Util/UUID.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> #include <stxxl/vector>
class ExtractionContainers { class ExtractionContainers {
@ -58,20 +52,9 @@ public:
STXXLWayIDStartEndVector way_start_end_id_list; STXXLWayIDStartEndVector way_start_end_id_list;
const UUID uuid; const UUID uuid;
ExtractionContainers() { ExtractionContainers();
//Check if stxxl can be instantiated
stxxl::vector<unsigned> dummy_vector;
name_list.push_back("");
}
virtual ~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();
}
void PrepareData( void PrepareData(
const std::string & output_file_name, const std::string & output_file_name,

78
Extractor/ExtractionWay.h Normal file
View 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

View File

@ -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" #include "ExtractorCallbacks.h"
ExtractorCallbacks::ExtractorCallbacks() {externalMemory = NULL; stringMap = NULL; } #include "../DataStructures/Restriction.h"
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap) { #include "../Util/SimpleLogger.h"
externalMemory = ext;
stringMap = strMap; #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() { } ExtractorCallbacks::~ExtractorCallbacks() { }
@ -62,14 +87,14 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) {
parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1); parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1);
} }
if(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) << SimpleLogger().Write(logDEBUG) <<
"found way with bogus speed, id: " << parsed_way.id; "found way with bogus speed, id: " << parsed_way.id;
return; return;
} }
//Get the unique identifier for the street name //Get the unique identifier for the street name
const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); const StringMap::const_iterator & string_map_iterator = stringMap->find(parsed_way.name);
if(stringMap->end() == string_map_iterator) { if(stringMap->end() == string_map_iterator) {
parsed_way.nameID = externalMemory->name_list.size(); parsed_way.nameID = externalMemory->name_list.size();
externalMemory->name_list.push_back(parsed_way.name); externalMemory->name_list.push_back(parsed_way.name);

View File

@ -28,29 +28,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef EXTRACTORCALLBACKS_H_ #ifndef EXTRACTORCALLBACKS_H_
#define EXTRACTORCALLBACKS_H_ #define EXTRACTORCALLBACKS_H_
#include "ExtractionContainers.h"
#include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h" #include "ExtractorStructs.h"
#include "../typedefs.h"
#include "../DataStructures/Coordinate.h" #include <boost/unordered_map.hpp>
#include <cfloat>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include <boost/regex.hpp>
#include <string> #include <string>
#include <vector>
class ExtractionContainers;
struct ExtractionWay;
struct InputRestrictionContainer;
typedef boost::unordered_map<std::string, NodeID> StringMap;
class ExtractorCallbacks{ class ExtractorCallbacks{
private: private:
StringMap * stringMap; StringMap * stringMap;
ExtractionContainers * externalMemory; ExtractionContainers * externalMemory;
ExtractorCallbacks(); ExtractorCallbacks();
public: public:
explicit ExtractorCallbacks(ExtractionContainers * ext, StringMap * strMap); explicit ExtractorCallbacks(
ExtractionContainers * ext,
StringMap * strMap
);
~ExtractorCallbacks(); ~ExtractorCallbacks();

View File

@ -28,64 +28,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef EXTRACTORSTRUCTS_H_ #ifndef EXTRACTORSTRUCTS_H_
#define EXTRACTORSTRUCTS_H_ #define EXTRACTORSTRUCTS_H_
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h" #include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h" #include "../DataStructures/ImportNode.h"
#include "../DataStructures/QueryNode.h"
#include "../DataStructures/Restriction.h"
#include "../typedefs.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> #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 { struct ExtractorRelation {
ExtractorRelation() : type(unknown){} ExtractorRelation() : type(unknown){}
enum { enum {
@ -94,49 +42,34 @@ struct ExtractorRelation {
HashTable<std::string, std::string> keyVals; 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 { struct _WayIDStartAndEndEdge {
unsigned wayID; unsigned wayID;
NodeID firstStart; NodeID firstStart;
NodeID firstTarget; NodeID firstTarget;
NodeID lastStart; NodeID lastStart;
NodeID lastTarget; NodeID lastTarget;
_WayIDStartAndEndEdge() : wayID(UINT_MAX), firstStart(UINT_MAX), firstTarget(UINT_MAX), lastStart(UINT_MAX), lastTarget(UINT_MAX) {} _WayIDStartAndEndEdge()
_WayIDStartAndEndEdge(unsigned w, NodeID fs, NodeID ft, NodeID ls, NodeID lt) : wayID(w), firstStart(fs), firstTarget(ft), lastStart(ls), lastTarget(lt) {} :
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() { 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)()); 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; 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; return a.wayID < b.wayID;
} }
value_type max_value() { 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; typedef NodeID value_type;
bool operator () (const NodeID a, const NodeID b) const { bool operator ()(
const NodeID a,
const NodeID b
) const {
return a < b; return a < b;
} }
value_type max_value() { value_type max_value() {
@ -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; typedef ExternalMemoryNode value_type;
bool operator () ( bool operator () (
const ExternalMemoryNode & a, 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_ */ #endif /* EXTRACTORSTRUCTS_H_ */

View 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

View File

@ -27,21 +27,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "PBFParser.h" #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; GOOGLE_PROTOBUF_VERIFY_VERSION;
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
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); input.open(fileName, std::ios::in | std::ios::binary);
if (!input) { if (!input) {
throw OSRMException("pbf file not found."); throw OSRMException("pbf file not found.");
} }
#ifndef NDEBUG
blockCount = 0; blockCount = 0;
groupCount = 0; groupCount = 0;
#endif
} }
PBFParser::~PBFParser() { PBFParser::~PBFParser() {
@ -50,18 +74,17 @@ PBFParser::~PBFParser() {
} }
// Clean up any leftover ThreadData objects in the queue // Clean up any leftover ThreadData objects in the queue
_ThreadData* td; _ThreadData* thread_data;
while (threadDataQueue->try_pop(td)) { while (threadDataQueue->try_pop(thread_data))
delete td; {
delete thread_data;
} }
google::protobuf::ShutdownProtobufLibrary(); google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG
SimpleLogger().Write(logDEBUG) << SimpleLogger().Write(logDEBUG) <<
"parsed " << blockCount << "parsed " << blockCount <<
" blocks from pbf with " << groupCount << " blocks from pbf with " << groupCount <<
" groups"; " groups";
#endif
} }
inline bool PBFParser::ReadHeader() { inline bool PBFParser::ReadHeader() {
@ -194,12 +217,15 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
#pragma omp parallel for schedule ( guided ) #pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_nodes; ++i) { for(int i = 0; i < number_of_nodes; ++i) {
ImportNode &n = extracted_nodes_vector[i]; ImportNode & import_node = extracted_nodes_vector[i];
ParseNodeInLua( n, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); ParseNodeInLua(
import_node,
scripting_environment.getLuaStateForThreadID(omp_get_thread_num())
);
} }
BOOST_FOREACH(const ImportNode &n, extracted_nodes_vector) { BOOST_FOREACH(const ImportNode &import_node, extracted_nodes_vector) {
extractor_callbacks->nodeFunction(n); extractor_callbacks->nodeFunction(import_node);
} }
} }
@ -232,12 +258,12 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
break; break;
} }
} }
if ("restriction" == key) { if ( ("restriction" == key) && (val.find("only_") == 0) )
if(val.find("only_") == 0) { {
isOnlyRestriction = true; isOnlyRestriction = true;
}
} }
if ("except" == key) { if ("except" == key)
{
except_tag_string = val; except_tag_string = val;
} }
} }
@ -326,18 +352,23 @@ inline void PBFParser::parseWay(_ThreadData * threadData) {
#pragma omp parallel for schedule ( guided ) #pragma omp parallel for schedule ( guided )
for(int i = 0; i < number_of_ways; ++i) { for(int i = 0; i < number_of_ways; ++i) {
ExtractionWay & w = parsed_way_vector[i]; ExtractionWay & extraction_way = parsed_way_vector[i];
if(2 > w.path.size()) { if (2 > extraction_way.path.size())
{
continue; 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) { BOOST_FOREACH(ExtractionWay & extraction_way, parsed_way_vector) {
if(2 > w.path.size()) { if (2 > extraction_way.path.size())
{
continue; 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) { inline void PBFParser::loadBlock(_ThreadData * threadData) {
#ifndef NDEBUG
++blockCount; ++blockCount;
#endif
threadData->currentGroupID = 0; threadData->currentGroupID = 0;
threadData->currentEntityID = 0; threadData->currentEntityID = 0;
} }

View File

@ -29,24 +29,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define PBFPARSER_H_ #define PBFPARSER_H_
#include "BaseParser.h" #include "BaseParser.h"
#include "../DataStructures/Coordinate.h"
#include "../DataStructures/HashTable.h"
#include "../DataStructures/ConcurrentQueue.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/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
#include <osmpbf/fileformat.pb.h> #include <osmpbf/fileformat.pb.h>
#include <osmpbf/osmformat.pb.h> #include <osmpbf/osmformat.pb.h>
#include <zlib.h> #include <fstream>
class PBFParser : public BaseParser { class PBFParser : public BaseParser {
@ -73,7 +63,11 @@ class PBFParser : public BaseParser {
}; };
public: public:
PBFParser(const char * fileName, ExtractorCallbacks* ec, ScriptingEnvironment& se); PBFParser(
const char * fileName,
ExtractorCallbacks* ec,
ScriptingEnvironment& se
);
virtual ~PBFParser(); virtual ~PBFParser();
inline bool ReadHeader(); inline bool ReadHeader();
@ -99,11 +93,8 @@ private:
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024; static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024; static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
#ifndef NDEBUG
/* counting the number of read blocks and groups */
unsigned groupCount; unsigned groupCount;
unsigned blockCount; unsigned blockCount;
#endif
std::fstream input; // the input stream to parse std::fstream input; // the input stream to parse
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue; boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;

View File

@ -27,6 +27,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ScriptingEnvironment.h" #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() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
SimpleLogger().Write() << "Using script " << fileName; SimpleLogger().Write() << "Using script " << fileName;

View File

@ -28,17 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef SCRIPTINGENVIRONMENT_H_ #ifndef SCRIPTINGENVIRONMENT_H_
#define 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> #include <vector>
struct lua_State;
class ScriptingEnvironment { class ScriptingEnvironment {
public: public:
ScriptingEnvironment(); ScriptingEnvironment();

View File

@ -27,16 +27,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "XMLParser.h" #include "XMLParser.h"
#include "ExtractorStructs.h" #include "ExtractionWay.h"
#include "../DataStructures/HashTable.h" #include "../DataStructures/HashTable.h"
#include "../DataStructures/ImportNode.h"
#include "../DataStructures/InputReaderFactory.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> #include <boost/ref.hpp>
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) { XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) {
SimpleLogger().Write(logWARNING) <<
"Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf";
inputReader = inputReaderFactory(filename); inputReader = inputReaderFactory(filename);
} }
@ -59,7 +63,7 @@ bool XMLParser::Parse() {
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) {
ImportNode n = _ReadXMLNode(); ImportNode n = _ReadXMLNode();
ParseNodeInLua( n, luaState ); ParseNodeInLua( n, lua_state );
extractor_callbacks->nodeFunction(n); extractor_callbacks->nodeFunction(n);
// if(!extractor_callbacks->nodeFunction(n)) // if(!extractor_callbacks->nodeFunction(n))
// std::cerr << "[XMLParser] dense node not parsed" << std::endl; // std::cerr << "[XMLParser] dense node not parsed" << std::endl;
@ -67,7 +71,7 @@ bool XMLParser::Parse() {
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
ExtractionWay way = _ReadXMLWay( ); ExtractionWay way = _ReadXMLWay( );
ParseWayInLua( way, luaState ); ParseWayInLua( way, lua_state );
extractor_callbacks->wayFunction(way); extractor_callbacks->wayFunction(way);
// if(!extractor_callbacks->wayFunction(way)) // if(!extractor_callbacks->wayFunction(way))
// std::cerr << "[PBFParser] way not parsed" << std::endl; // std::cerr << "[PBFParser] way not parsed" << std::endl;

View File

@ -28,18 +28,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef XMLPARSER_H_ #ifndef XMLPARSER_H_
#define XMLPARSER_H_ #define XMLPARSER_H_
#include "ExtractorCallbacks.h"
#include "BaseParser.h" #include "BaseParser.h"
#include "../DataStructures/Coordinate.h"
#include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h"
#include "../typedefs.h"
#include <libxml/xmlreader.h> #include <libxml/xmlreader.h>
class XMLParser : public BaseParser { class XMLParser : public BaseParser {
public: public:
XMLParser(const char* filename, ExtractorCallbacks* ec, ScriptingEnvironment& se); XMLParser(
const char* filename,
ExtractorCallbacks* ec,
ScriptingEnvironment& se
);
bool ReadHeader(); bool ReadHeader();
bool Parse(); bool Parse();

84
Include/osrm/Coordinate.h Normal file
View 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_ */

View File

@ -43,4 +43,3 @@ namespace http {
} }
#endif //HTTP_HEADER_H #endif //HTTP_HEADER_H

View File

@ -29,10 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define REPLY_H #define REPLY_H
#include "Header.h" #include "Header.h"
#include "../../Util/StringUtil.h"
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/foreach.hpp>
#include <vector> #include <vector>
@ -48,24 +46,26 @@ const std::string badRequestString = "HTTP/1.0 400 Bad Request\r\n";
const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n"; const std::string internalServerErrorString = "HTTP/1.0 500 Internal Server Error\r\n";
class Reply { class Reply {
public: public:
enum status_type { enum status_type {
ok = 200, ok = 200,
badRequest = 400, badRequest = 400,
internalServerError = 500 internalServerError = 500
} status; } status;
std::vector<Header> headers; std::vector<Header> headers;
std::vector<boost::asio::const_buffer> toBuffers(); std::vector<boost::asio::const_buffer> toBuffers();
std::vector<boost::asio::const_buffer> HeaderstoBuffers(); std::vector<boost::asio::const_buffer> HeaderstoBuffers();
std::vector<std::string> content; std::vector<std::string> content;
static Reply StockReply(status_type status); static Reply StockReply(status_type status);
void setSize(const unsigned size); void setSize(const unsigned size);
Reply(); void SetUncompressedSize();
private:
static std::string ToString(Reply::status_type status); Reply();
boost::asio::const_buffer ToBuffer(Reply::status_type status); private:
static std::string ToString(Reply::status_type status);
boost::asio::const_buffer ToBuffer(Reply::status_type status);
}; };
} }

View File

@ -28,8 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ROUTE_PARAMETERS_H #ifndef ROUTE_PARAMETERS_H
#define ROUTE_PARAMETERS_H #define ROUTE_PARAMETERS_H
#include "../../DataStructures/Coordinate.h" #include <osrm/Coordinate.h>
#include "../../DataStructures/HashTable.h"
#include <boost/fusion/container/vector.hpp> #include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic.hpp> #include <boost/fusion/sequence/intrinsic.hpp>
@ -46,7 +45,9 @@ struct RouteParameters {
geometry(true), geometry(true),
compression(true), compression(true),
deprecatedAPI(false), deprecatedAPI(false),
checkSum(-1) {} checkSum(-1)
{ }
short zoomLevel; short zoomLevel;
bool printInstructions; bool printInstructions;
bool alternateRoute; bool alternateRoute;
@ -60,10 +61,9 @@ struct RouteParameters {
std::string language; std::string language;
std::vector<std::string> hints; std::vector<std::string> hints;
std::vector<FixedPointCoordinate> coordinates; std::vector<FixedPointCoordinate> coordinates;
typedef HashTable<std::string, std::string>::const_iterator OptionsIterator;
void setZoomLevel(const short i) { void setZoomLevel(const short i) {
if (18 > i && 0 < i) { if (18 >= i && 0 <= i) {
zoomLevel = i; zoomLevel = i;
} }
} }
@ -97,8 +97,10 @@ struct RouteParameters {
} }
void addHint(const std::string & s) { void addHint(const std::string & s) {
hints.resize(coordinates.size()); hints.resize( coordinates.size() );
hints.back() = s; if( !hints.empty() ) {
hints.back() = s;
}
} }
void setLanguage(const std::string & s) { void setLanguage(const std::string & s) {

View File

@ -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. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <cstdlib>
int main( int argc, char* argv[] ) { #ifndef SERVER_PATH_H
size_t size = sizeof(void*); #define SERVER_PATH_H
if ( 4 == size ) {
return 0; #include <boost/unordered_map.hpp>
} #include <boost/filesystem.hpp>
return 1;
} #include <string>
typedef boost::unordered_map<const std::string, boost::filesystem::path> ServerPaths;
#endif //SERVER_PATH_H

View File

@ -28,38 +28,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef OSRM_H #ifndef OSRM_H
#define OSRM_H #define OSRM_H
#include "OSRM.h" #include <boost/scoped_ptr.hpp>
#include "../Plugins/BasePlugin.h" #include <osrm/Reply.h>
#include "../Plugins/HelloWorldPlugin.h" #include <osrm/RouteParameters.h>
#include "../Plugins/LocatePlugin.h" #include <osrm/ServerPaths.h>
#include "../Plugins/NearestPlugin.h"
#include "../Plugins/TimestampPlugin.h"
#include "../Plugins/ViaRoutePlugin.h"
#include "../Server/DataStructures/BaseDataFacade.h"
#include "../Server/DataStructures/InternalDataFacade.h"
#include "../Server/DataStructures/SharedBarriers.h"
#include "../Server/DataStructures/SharedDataFacade.h"
#include "../Server/DataStructures/RouteParameters.h"
#include "../Util/InputFileUtil.h"
#include "../Util/OSRMException.h"
#include "../Util/SimpleLogger.h"
#include <boost/assert.hpp> class OSRM_impl;
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <vector> class OSRM {
class OSRM : boost::noncopyable {
private: private:
typedef boost::unordered_map<std::string, BasePlugin *> PluginMap; OSRM_impl * OSRM_pimpl_;
public: public:
OSRM( OSRM(
const ServerPaths & paths, const ServerPaths & paths,
@ -67,14 +46,6 @@ public:
); );
~OSRM(); ~OSRM();
void RunQuery(RouteParameters & route_parameters, http::Reply & reply); 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

View File

@ -26,17 +26,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "OSRM.h" #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) 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>( query_data_facade = new InternalDataFacade<QueryEdge::EdgeData>(
server_paths server_paths
); );
} else {
query_data_facade = new SharedDataFacade<QueryEdge::EdgeData>( );
} }
//The following plugins handle all requests. //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) { BOOST_FOREACH(PluginMap::value_type & plugin_pointer, plugin_map) {
delete plugin_pointer.second; 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(); SimpleLogger().Write() << "loaded plugin: " << plugin->GetDescriptor();
if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) { if( plugin_map.find(plugin->GetDescriptor()) != plugin_map.end() ) {
delete plugin_map.find(plugin->GetDescriptor())->second; delete plugin_map.find(plugin->GetDescriptor())->second;
@ -79,7 +100,7 @@ void OSRM::RegisterPlugin(BasePlugin * plugin) {
plugin_map.emplace(plugin->GetDescriptor(), 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( const PluginMap::const_iterator & iter = plugin_map.find(
route_parameters.service route_parameters.service
); );
@ -90,18 +111,18 @@ void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
// lock update pending // lock update pending
boost::interprocess::scoped_lock< boost::interprocess::scoped_lock<
boost::interprocess::named_mutex boost::interprocess::named_mutex
> pending_lock(barrier.pending_update_mutex); > pending_lock(barrier->pending_update_mutex);
// lock query // lock query
boost::interprocess::scoped_lock< boost::interprocess::scoped_lock<
boost::interprocess::named_mutex boost::interprocess::named_mutex
> query_lock(barrier.query_mutex); > query_lock(barrier->query_mutex);
// unlock update pending // unlock update pending
pending_lock.unlock(); pending_lock.unlock();
// increment query count // increment query count
++(barrier.number_of_queries); ++(barrier->number_of_queries);
(static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade(); (static_cast<SharedDataFacade<QueryEdge::EdgeData>* >(query_data_facade))->CheckAndReloadFacade();
} }
@ -111,21 +132,36 @@ void OSRM::RunQuery(RouteParameters & route_parameters, http::Reply & reply) {
// lock query // lock query
boost::interprocess::scoped_lock< boost::interprocess::scoped_lock<
boost::interprocess::named_mutex boost::interprocess::named_mutex
> query_lock(barrier.query_mutex); > query_lock(barrier->query_mutex);
// decrement query count // decrement query count
--(barrier.number_of_queries); --(barrier->number_of_queries);
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
0 <= barrier.number_of_queries, 0 <= barrier->number_of_queries,
"invalid number of queries" "invalid number of queries"
); );
// notify all processes that were waiting for this condition // notify all processes that were waiting for this condition
if (0 == barrier.number_of_queries) { if (0 == barrier->number_of_queries) {
barrier.no_running_queries_condition.notify_all(); barrier->no_running_queries_condition.notify_all();
} }
} }
} else { } else {
reply = http::Reply::StockReply(http::Reply::badRequest); reply = http::Reply::StockReply(http::Reply::badRequest);
} }
} }
// proxy code for compilation firewall
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
View 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

View File

@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BASEPLUGIN_H_ #ifndef BASEPLUGIN_H_
#define BASEPLUGIN_H_ #define BASEPLUGIN_H_
#include "../DataStructures/Coordinate.h" #include <osrm/Coordinate.h>
#include "../Server/DataStructures/RouteParameters.h" #include <osrm/Reply.h>
#include "../Server/Http/Reply.h" #include <osrm/RouteParameters.h>
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -68,7 +68,6 @@ public:
} }
reply.status = http::Reply::ok; reply.status = http::Reply::ok;
reply.content.push_back ("{"); reply.content.push_back ("{");
reply.content.push_back ("\"version\":0.3,");
if( if(
!facade->LocateClosestEndPointForCoordinate( !facade->LocateClosestEndPointForCoordinate(
routeParameters.coordinates[0], routeParameters.coordinates[0],
@ -82,15 +81,14 @@ public:
reply.status = http::Reply::ok; reply.status = http::Reply::ok;
reply.content.push_back ("\"status\":0,"); reply.content.push_back ("\"status\":0,");
reply.content.push_back ("\"mapped_coordinate\":"); reply.content.push_back ("\"mapped_coordinate\":");
convertInternalLatLonToString(result.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
reply.content.push_back("["); reply.content.push_back("[");
reply.content.push_back(tmp); reply.content.push_back(tmp);
convertInternalLatLonToString(result.lon, tmp); FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
reply.content.push_back(","); reply.content.push_back(",");
reply.content.push_back(tmp); reply.content.push_back(tmp);
reply.content.push_back("]"); reply.content.push_back("]");
} }
reply.content.push_back(",\"transactionId\": \"OSRM Routing Engine JSON Locate (v0.3)\"");
reply.content.push_back("}"); reply.content.push_back("}");
reply.headers.resize(3); reply.headers.resize(3);
if(!routeParameters.jsonpParameter.empty()) { if(!routeParameters.jsonpParameter.empty()) {

View File

@ -25,13 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef NearestPlugin_H_ #ifndef NEAREST_PLUGIN_H
#define NearestPlugin_H_ #define NEAREST_PLUGIN_H
#include "BasePlugin.h" #include "BasePlugin.h"
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../Util/StringUtil.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. * This Plugin locates the nearest point on a street in the road network for a given coordinate.
*/ */
@ -44,11 +46,15 @@ public:
facade(facade), facade(facade),
descriptor_string("nearest") descriptor_string("nearest")
{ {
descriptorTable.insert(std::make_pair("" , 0)); //default descriptor descriptorTable.emplace("", 0); //default descriptor
descriptorTable.insert(std::make_pair("json", 1)); descriptorTable.emplace("json", 1);
} }
const std::string & GetDescriptor() const { return descriptor_string; } const std::string & GetDescriptor() const { return descriptor_string; }
void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) {
void HandleRequest(
const RouteParameters & routeParameters,
http::Reply& reply
) {
//check number of parameters //check number of parameters
if(!routeParameters.coordinates.size()) { if(!routeParameters.coordinates.size()) {
reply = http::Reply::StockReply(http::Reply::badRequest); reply = http::Reply::StockReply(http::Reply::badRequest);
@ -75,32 +81,26 @@ public:
} }
reply.status = http::Reply::ok; reply.status = http::Reply::ok;
reply.content.push_back("{"); reply.content.push_back("{\"status\":");
reply.content.push_back("\"version\":0.3,");
reply.content.push_back("\"status\":");
if(UINT_MAX != result.edgeBasedNode) { if(UINT_MAX != result.edgeBasedNode) {
reply.content.push_back("0,"); reply.content.push_back("0,");
} else { } else {
reply.content.push_back("207,"); reply.content.push_back("207,");
} }
reply.content.push_back("\"mapped_coordinate\":"); reply.content.push_back("\"mapped_coordinate\":[");
reply.content.push_back("[");
if(UINT_MAX != result.edgeBasedNode) { if(UINT_MAX != result.edgeBasedNode) {
convertInternalLatLonToString(result.location.lat, temp_string); FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
reply.content.push_back(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(",");
reply.content.push_back(temp_string); 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) { if(UINT_MAX != result.edgeBasedNode) {
facade->GetName(result.nodeBasedEdgeNameID, temp_string); facade->GetName(result.nodeBasedEdgeNameID, temp_string);
reply.content.push_back(temp_string); reply.content.push_back(temp_string);
} }
reply.content.push_back("\""); reply.content.push_back("\"}");
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON Nearest (v0.3)\"");
reply.content.push_back("}");
reply.headers.resize(3); reply.headers.resize(3);
if( !routeParameters.jsonpParameter.empty() ) { if( !routeParameters.jsonpParameter.empty() ) {
reply.content.push_back(")"); reply.content.push_back(")");
@ -125,8 +125,8 @@ public:
private: private:
DataFacadeT * facade; DataFacadeT * facade;
HashTable<std::string, unsigned> descriptorTable; boost::unordered_map<std::string, unsigned> descriptorTable;
std::string descriptor_string; std::string descriptor_string;
}; };
#endif /* NearestPlugin_H_ */ #endif /* NEAREST_PLUGIN_H */

View File

@ -48,13 +48,11 @@ public:
reply.status = http::Reply::ok; reply.status = http::Reply::ok;
reply.content.push_back("{"); reply.content.push_back("{");
reply.content.push_back("\"version\":0.3,");
reply.content.push_back("\"status\":"); reply.content.push_back("\"status\":");
reply.content.push_back("0,"); reply.content.push_back("0,");
reply.content.push_back("\"timestamp\":\""); reply.content.push_back("\"timestamp\":\"");
reply.content.push_back(facade->GetTimestamp()); reply.content.push_back(facade->GetTimestamp());
reply.content.push_back("\""); reply.content.push_back("\"");
reply.content.push_back(",\"transactionId\":\"OSRM Routing Engine JSON timestamp (v0.3)\"");
reply.content.push_back("}"); reply.content.push_back("}");
reply.headers.resize(3); reply.headers.resize(3);
if("" != routeParameters.jsonpParameter) { if("" != routeParameters.jsonpParameter) {

View File

@ -83,7 +83,7 @@ public:
RawRouteData rawRoute; RawRouteData rawRoute;
rawRoute.checkSum = facade->GetCheckSum(); rawRoute.checkSum = facade->GetCheckSum();
bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum); const bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum);
std::vector<std::string> textCoord; std::vector<std::string> textCoord;
for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) { for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) {
if( !checkCoord(routeParameters.coordinates[i]) ) { if( !checkCoord(routeParameters.coordinates[i]) ) {
@ -110,12 +110,13 @@ public:
); );
} }
PhantomNodes segmentPhantomNodes;
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) { for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
PhantomNodes segmentPhantomNodes;
segmentPhantomNodes.startPhantom = phantomNodeVector[i]; segmentPhantomNodes.startPhantom = phantomNodeVector[i];
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1]; segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes); rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes);
} }
if( if(
( routeParameters.alternateRoute ) && ( routeParameters.alternateRoute ) &&
(1 == rawRoute.segmentEndCoordinates.size()) (1 == rawRoute.segmentEndCoordinates.size())
@ -175,7 +176,7 @@ public:
phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom; phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom;
desc->SetConfig(descriptorConfig); desc->SetConfig(descriptorConfig);
desc->Run(reply, rawRoute, phantomNodes, facade); desc->Run(rawRoute, phantomNodes, facade, reply);
if("" != routeParameters.jsonpParameter) { if("" != routeParameters.jsonpParameter) {
reply.content.push_back(")\n"); reply.content.push_back(")\n");
} }

View File

@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BasicRoutingInterface.h" #include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h" #include "../DataStructures/SearchEngineData.h"
#include <boost/foreach.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include <cmath> #include <cmath>
#include <vector> #include <vector>
@ -77,7 +78,8 @@ public:
void operator()( void operator()(
const PhantomNodes & phantom_node_pair, const PhantomNodes & phantom_node_pair,
RawRouteData & raw_route_data) { RawRouteData & raw_route_data
) {
if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) || if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) ||
phantom_node_pair.PhantomNodesHaveEqualLocation() phantom_node_pair.PhantomNodesHaveEqualLocation()
) { ) {
@ -212,12 +214,19 @@ public:
approximated_reverse_sharing[v] = reverse_heap1.GetKey(u); approximated_reverse_sharing[v] = reverse_heap1.GetKey(u);
} else { } else {
//sharing (s) = sharing (t) //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; std::vector<NodeID> nodes_that_passed_preselection;
BOOST_FOREACH(const NodeID node, via_node_candidate_list) { 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); int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node);
bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)); bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON));
bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA); 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 //Unpack shortest path and alternative, if they exist
if(INT_MAX != upper_bound_to_shortest_path_distance) { if(INT_MAX != upper_bound_to_shortest_path_distance) {
super::UnpackPath(packedShortestPath, 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; raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance;
} else { } else {
raw_route_data.lengthOfShortestPath = INT_MAX; raw_route_data.lengthOfShortestPath = INT_MAX;
} }
if(selectedViaNode != UINT_MAX) { if(selectedViaNode != UINT_MAX) {
retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, 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; raw_route_data.lengthOfAlternativePath = lengthOfViaPath;
} else { } else {
raw_route_data.lengthOfAlternativePath = INT_MAX; raw_route_data.lengthOfAlternativePath = INT_MAX;
@ -274,7 +285,7 @@ public:
private: private:
//unpack <s,..,v,..,t> by exploring search spaces from v //unpack <s,..,v,..,t> by exploring search spaces from v
inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2, inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2,
const NodeID s_v_middle, const NodeID v_t_middle, std::vector<_PathData> & unpackedPath) { const NodeID s_v_middle, const NodeID v_t_middle, std::vector<PathData> & unpackedPath) {
//unpack [s,v) //unpack [s,v)
std::vector<NodeID> packed_s_v_path, packed_v_t_path; std::vector<NodeID> packed_s_v_path, packed_v_t_path;
super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path); super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path);
@ -305,19 +316,19 @@ private:
std::vector<NodeID> partiallyUnpackedViaPath; std::vector<NodeID> partiallyUnpackedViaPath;
NodeID s_v_middle = UINT_MAX; NodeID s_v_middle = UINT_MAX;
int upperBoundFor_s_v_Path = INT_MAX;//compute path <s,..,v> by reusing forward search from s int upperBoundFor_s_vPath = INT_MAX;//compute path <s,..,v> by reusing forward search from s
newBackwardHeap.Insert(via_node, 0, via_node); newBackwardHeap.Insert(via_node, 0, via_node);
while (0 < newBackwardHeap.Size()) { 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 //compute path <v,..,t> by reusing backward search from node t
NodeID v_t_middle = UINT_MAX; NodeID v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX; int upperBoundFor_v_tPath = INT_MAX;
newForwardHeap.Insert(via_node, 0, via_node); newForwardHeap.Insert(via_node, 0, via_node);
while (0 < newForwardHeap.Size() ) { 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) if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle)
return; return;
@ -469,28 +480,28 @@ private:
std::vector < NodeID > packed_v_t_path; std::vector < NodeID > packed_v_t_path;
*s_v_middle = UINT_MAX; *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 //compute path <s,..,v> by reusing forward search from s
newBackwardHeap.Insert(candidate.node, 0, candidate.node); newBackwardHeap.Insert(candidate.node, 0, candidate.node);
while (newBackwardHeap.Size() > 0) { while (newBackwardHeap.Size() > 0) {
super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_v_Path, 2*offset, false); super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_vPath, 2*offset, false);
} }
if(INT_MAX == upperBoundFor_s_v_Path) if(INT_MAX == upperBoundFor_s_vPath)
return false; return false;
//compute path <v,..,t> by reusing backward search from t //compute path <v,..,t> by reusing backward search from t
*v_t_middle = UINT_MAX; *v_t_middle = UINT_MAX;
int upperBoundFor_v_t_Path = INT_MAX; int upperBoundFor_v_tPath = INT_MAX;
newForwardHeap.Insert(candidate.node, 0, candidate.node); newForwardHeap.Insert(candidate.node, 0, candidate.node);
while (newForwardHeap.Size() > 0) { while (newForwardHeap.Size() > 0) {
super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_t_Path, 2*offset, true); super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_tPath, 2*offset, true);
} }
if(INT_MAX == upperBoundFor_v_t_Path) if(INT_MAX == upperBoundFor_v_tPath)
return false; return false;
*lengthOfViaPath = upperBoundFor_s_v_Path + upperBoundFor_v_t_Path; *lengthOfViaPath = upperBoundFor_s_vPath + upperBoundFor_v_tPath;
//retrieve packed paths //retrieve packed paths
super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, *s_v_middle, packed_s_v_path); 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; unpackedUntilDistance = 0;
//Traverse path s-->v //Traverse path s-->v
for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) { for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) {
@ -587,7 +598,7 @@ private:
} }
} }
lengthOfPathT_Test_Path += unpackedUntilDistance; lengthOfPathT_TestPath += unpackedUntilDistance;
//Run actual T-Test query and compare if distances equal. //Run actual T-Test query and compare if distances equal.
engine_working_data.InitializeOrClearThirdThreadLocalStorage( engine_working_data.InitializeOrClearThirdThreadLocalStorage(
super::facade->GetNumberOfNodes() super::facade->GetNumberOfNodes()
@ -608,7 +619,7 @@ private:
super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false); super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false);
} }
} }
return (_upperBound <= lengthOfPathT_Test_Path); return (_upperBound <= lengthOfPathT_TestPath);
} }
}; };

View File

@ -136,7 +136,7 @@ public:
inline void UnpackPath( inline void UnpackPath(
const std::vector<NodeID> & packed_path, const std::vector<NodeID> & packed_path,
std::vector<_PathData> & unpacked_path std::vector<PathData> & unpacked_path
) const { ) const {
const unsigned packed_path_size = packed_path.size(); const unsigned packed_path_size = packed_path.size();
std::stack<std::pair<NodeID, NodeID> > recursion_stack; std::stack<std::pair<NodeID, NodeID> > recursion_stack;
@ -199,7 +199,7 @@ public:
} else { } else {
BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut"); BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut");
unpacked_path.push_back( unpacked_path.push_back(
_PathData( PathData(
ed.id, ed.id,
facade->GetNameIndexFromEdgeID(ed.id), facade->GetNameIndexFromEdgeID(ed.id),
facade->GetTurnInstructionForEdgeID(ed.id), facade->GetTurnInstructionForEdgeID(ed.id),

View File

@ -29,9 +29,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SHORTESTPATHROUTING_H_ #define SHORTESTPATHROUTING_H_
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/foreach.hpp>
#include "BasicRoutingInterface.h" #include "BasicRoutingInterface.h"
#include "../DataStructures/SearchEngineData.h" #include "../DataStructures/SearchEngineData.h"
#include "../typedefs.h"
template<class DataFacadeT> template<class DataFacadeT>
class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{ class ShortestPathRouting : public BasicRoutingInterface<DataFacadeT>{
@ -51,7 +53,7 @@ public:
~ShortestPathRouting() {} ~ShortestPathRouting() {}
void operator()( void operator()(
std::vector<PhantomNodes> & phantom_nodes_vector, const std::vector<PhantomNodes> & phantom_nodes_vector,
RawRouteData & raw_route_data RawRouteData & raw_route_data
) const { ) const {
BOOST_FOREACH( BOOST_FOREACH(
@ -66,13 +68,12 @@ public:
} }
int distance1 = 0; int distance1 = 0;
int distance2 = 0; int distance2 = 0;
bool search_from_1st_node = true; bool search_from_1st_node = true;
bool search_from_2nd_node = true; bool search_from_2nd_node = true;
NodeID middle1 = UINT_MAX; NodeID middle1 = UINT_MAX;
NodeID middle2 = UINT_MAX; NodeID middle2 = UINT_MAX;
std::vector<NodeID> packed_path1; std::vector<std::vector<NodeID> > packed_legs1(phantom_nodes_vector.size());
std::vector<NodeID> packed_path2; std::vector<std::vector<NodeID> > packed_legs2(phantom_nodes_vector.size());
engine_working_data.InitializeOrClearFirstThreadLocalStorage( engine_working_data.InitializeOrClearFirstThreadLocalStorage(
super::facade->GetNumberOfNodes() super::facade->GetNumberOfNodes()
@ -89,10 +90,10 @@ public:
QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2); QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2);
QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2); QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2);
int current_leg = 0;
//Get distance to next pair of target nodes. //Get distance to next pair of target nodes.
BOOST_FOREACH( BOOST_FOREACH(
const PhantomNodes & phantom_node_pair, const PhantomNodes & phantom_node_pair, phantom_nodes_vector
phantom_nodes_vector
){ ){
forward_heap1.Clear(); forward_heap2.Clear(); forward_heap1.Clear(); forward_heap2.Clear();
reverse_heap1.Clear(); reverse_heap2.Clear(); reverse_heap1.Clear(); reverse_heap2.Clear();
@ -109,27 +110,23 @@ public:
distance1-phantom_node_pair.startPhantom.weight1, distance1-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode phantom_node_pair.startPhantom.edgeBasedNode
); );
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
forward_heap2.Insert( forward_heap2.Insert(
phantom_node_pair.startPhantom.edgeBasedNode, phantom_node_pair.startPhantom.edgeBasedNode,
distance1-phantom_node_pair.startPhantom.weight1, distance1-phantom_node_pair.startPhantom.weight1,
phantom_node_pair.startPhantom.edgeBasedNode 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) { if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) {
forward_heap1.Insert( forward_heap1.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1, phantom_node_pair.startPhantom.edgeBasedNode+1,
distance2-phantom_node_pair.startPhantom.weight2, distance2-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1 phantom_node_pair.startPhantom.edgeBasedNode+1
); );
// INFO("fw1: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
forward_heap2.Insert( forward_heap2.Insert(
phantom_node_pair.startPhantom.edgeBasedNode+1, phantom_node_pair.startPhantom.edgeBasedNode+1,
distance2-phantom_node_pair.startPhantom.weight2, distance2-phantom_node_pair.startPhantom.weight2,
phantom_node_pair.startPhantom.edgeBasedNode+1 phantom_node_pair.startPhantom.edgeBasedNode+1
); );
// INFO("fw2: " << phantom_node_pair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
} }
//insert new backward nodes into backward heap, unadjusted. //insert new backward nodes into backward heap, unadjusted.
@ -138,15 +135,14 @@ public:
phantom_node_pair.targetPhantom.weight1, phantom_node_pair.targetPhantom.weight1,
phantom_node_pair.targetPhantom.edgeBasedNode phantom_node_pair.targetPhantom.edgeBasedNode
); );
// INFO("rv1: " << phantom_node_pair.targetPhantom.edgeBasedNode << ", w;" << phantom_node_pair.targetPhantom.weight1 );
if(phantom_node_pair.targetPhantom.isBidirected() ) { if(phantom_node_pair.targetPhantom.isBidirected() ) {
reverse_heap2.Insert( reverse_heap2.Insert(
phantom_node_pair.targetPhantom.edgeBasedNode+1, phantom_node_pair.targetPhantom.edgeBasedNode+1,
phantom_node_pair.targetPhantom.weight2, phantom_node_pair.targetPhantom.weight2,
phantom_node_pair.targetPhantom.edgeBasedNode+1 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( const int forward_offset = super::ComputeEdgeOffset(
phantom_node_pair.startPhantom phantom_node_pair.startPhantom
); );
@ -177,6 +173,7 @@ public:
); );
} }
} }
if( !reverse_heap2.Empty() ) { if( !reverse_heap2.Empty() ) {
while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){ while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){
if( !forward_heap2.Empty() ){ if( !forward_heap2.Empty() ){
@ -225,14 +222,18 @@ public:
); );
//Unpack paths if they exist //Unpack paths if they exist
std::vector<NodeID> temporary_packed_path1; std::vector<NodeID> temporary_packed_leg1;
std::vector<NodeID> temporary_packed_path2; 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) { if(INT_MAX != local_upper_bound1) {
super::RetrievePackedPathFromHeap( super::RetrievePackedPathFromHeap(
forward_heap1, forward_heap1,
reverse_heap1, reverse_heap1,
middle1, middle1,
temporary_packed_path1 temporary_packed_leg1
); );
} }
@ -241,100 +242,123 @@ public:
forward_heap2, forward_heap2,
reverse_heap2, reverse_heap2,
middle2, middle2,
temporary_packed_path2 temporary_packed_leg2
); );
} }
//if one of the paths was not found, replace it with the other one. //if one of the paths was not found, replace it with the other one.
if( temporary_packed_path1.empty() ) { if( temporary_packed_leg1.empty() ) {
temporary_packed_path1.insert( temporary_packed_leg1.insert(
temporary_packed_path1.end(), temporary_packed_leg1.end(),
temporary_packed_path2.begin(), temporary_packed_leg2.begin(),
temporary_packed_path2.end() temporary_packed_leg2.end()
); );
local_upper_bound1 = local_upper_bound2; local_upper_bound1 = local_upper_bound2;
} }
if( temporary_packed_path2.empty() ) { if( temporary_packed_leg2.empty() ) {
temporary_packed_path2.insert( temporary_packed_leg2.insert(
temporary_packed_path2.end(), temporary_packed_leg2.end(),
temporary_packed_path1.begin(), temporary_packed_leg1.begin(),
temporary_packed_path1.end() temporary_packed_leg1.end()
); );
local_upper_bound2 = local_upper_bound1; local_upper_bound2 = local_upper_bound1;
} }
// SimpleLogger().Write() << "fetched packed paths";
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
!temporary_packed_path1.empty() || !temporary_packed_leg1.empty() ||
!temporary_packed_path2.empty(), !temporary_packed_leg2.empty(),
"tempory packed paths empty" "tempory packed paths empty"
); );
//Plug paths together, s.t. end of packed path is begin of temporary packed path BOOST_ASSERT(
if( !packed_path1.empty() && !packed_path2.empty() ) { (0 == current_leg) || !packed_legs1[current_leg-1].empty()
if( );
temporary_packed_path1.front() == BOOST_ASSERT(
temporary_packed_path2.front() (0 == current_leg) || !packed_legs2[current_leg-1].empty()
) { );
//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"
);
if( packed_path1.back() == temporary_packed_path1.front()) { if( 0 < current_leg ) {
packed_path2.clear(); const NodeID end_id_of_segment1 = packed_legs1[current_leg-1].back();
packed_path2.insert( const NodeID end_id_of_segment2 = packed_legs2[current_leg-1].back();
packed_path2.end(), BOOST_ASSERT( !temporary_packed_leg1.empty() );
packed_path1.begin(), const NodeID start_id_of_leg1 = temporary_packed_leg1.front();
packed_path1.end() 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 )
) {
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 { } else
packed_path1.clear(); if( start_id_of_leg2 != last_id_of_packed_legs2 ) {
packed_path1.insert( packed_legs2 = packed_legs1;
packed_path1.end(), BOOST_ASSERT(
packed_path2.begin(), start_id_of_leg2 == temporary_packed_leg2.front()
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( BOOST_ASSERT(
packed_path1.end(), packed_legs1.size() == packed_legs2.size()
temporary_packed_path1.begin(),
temporary_packed_path1.end()
);
packed_path2.insert(
packed_path2.end(),
temporary_packed_path2.begin(),
temporary_packed_path2.end()
); );
packed_legs1[current_leg].insert(
packed_legs1[current_leg].end(),
temporary_packed_leg1.begin(),
temporary_packed_leg1.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( if(
(packed_path1.back() == packed_path2.back()) && (packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) &&
phantom_node_pair.targetPhantom.isBidirected() 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_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1);
search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode); 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; distance1 = local_upper_bound1;
distance2 = local_upper_bound2; distance2 = local_upper_bound2;
++current_leg;
} }
if( distance1 > distance2 ) { 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); raw_route_data.lengthOfShortestPath = std::min(distance1, distance2);
} }
}; };

View File

@ -42,7 +42,7 @@ struct APIGrammar : qi::grammar<Iterator> {
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> 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)]; 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)]; instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)]; geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
@ -53,16 +53,17 @@ struct APIGrammar : qi::grammar<Iterator> {
alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)]; alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)];
old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)]; old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)];
string = +(qi::char_("a-zA-Z")); string = +(qi::char_("a-zA-Z"));
stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); 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> api_call, query;
qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint, 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; cmp, alt_route, old_API;
HandlerT * handler; HandlerT * handler;
}; };
#endif /* APIGRAMMAR_H_ */ #endif /* APIGRAMMAR_H_ */

240
Server/Connection.cpp Normal file
View 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();
}
}

View File

@ -29,27 +29,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define CONNECTION_H #define CONNECTION_H
#include "Http/CompressionType.h" #include "Http/CompressionType.h"
#include "RequestHandler.h" #include "Http/Request.h"
#include "RequestParser.h"
#include <osrm/Reply.h>
#include <boost/array.hpp> #include <boost/array.hpp>
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp> #include <boost/enable_shared_from_this.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
// #include <zlib.h>
#include <string> #include <string>
#include <vector> #include <vector>
class RequestHandler;
namespace http { namespace http {
class RequestParser;
/// Represents a single connection from a client. /// Represents a single connection from a client.
class Connection : public boost::enable_shared_from_this<Connection>, class Connection : public boost::enable_shared_from_this<Connection>,
private boost::noncopyable { private boost::noncopyable {
@ -57,262 +54,36 @@ public:
explicit Connection( explicit Connection(
boost::asio::io_service& io_service, boost::asio::io_service& io_service,
RequestHandler& handler RequestHandler& handler
) : strand(io_service), TCP_socket(io_service), request_handler(handler) { } );
boost::asio::ip::tcp::socket& socket() { ~Connection();
return TCP_socket;
} boost::asio::ip::tcp::socket& socket();
/// Start the first asynchronous operation for the connection. /// Start the first asynchronous operation for the connection.
void start() { 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)
)
);
}
private: private:
void handle_read( void handle_read(
const boost::system::error_code& e, const boost::system::error_code& e,
std::size_t bytes_transferred 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. /// Handle completion of a write operation.
void handle_write(const boost::system::error_code& e) { 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 compressBufferCollection( void compressBufferCollection(
std::vector<std::string> uncompressed_data, std::vector<std::string> uncompressed_data,
CompressionType compression_type, CompressionType compression_type,
std::vector<char> & compressed_data 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::io_service::strand strand;
boost::asio::ip::tcp::socket TCP_socket; boost::asio::ip::tcp::socket TCP_socket;
RequestHandler& request_handler; RequestHandler& request_handler;
boost::array<char, 8192> incoming_data_buffer; boost::array<char, 8192> incoming_data_buffer;
Request request; Request request;
RequestParser request_parser; RequestParser * request_parser;
Reply reply; Reply reply;
}; };

View File

@ -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 //Exposes all data access interfaces to the algorithms via base class ptr
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/EdgeBasedNode.h" #include "../../DataStructures/EdgeBasedNode.h"
#include "../../DataStructures/ImportNode.h" #include "../../DataStructures/ImportNode.h"
#include "../../DataStructures/PhantomNodes.h" #include "../../DataStructures/PhantomNodes.h"
@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../Util/StringUtil.h" #include "../../Util/StringUtil.h"
#include "../../typedefs.h" #include "../../typedefs.h"
#include <osrm/Coordinate.h>
#include <string> #include <string>
template<class EdgeDataT> template<class EdgeDataT>
@ -113,7 +114,7 @@ public:
std::string GetEscapedNameForNameID(const unsigned name_id) const { std::string GetEscapedNameForNameID(const unsigned name_id) const {
std::string temporary_string; std::string temporary_string;
GetName(name_id, temporary_string); GetName(name_id, temporary_string);
return HTMLEntitize(temporary_string); return EscapeJSONString(temporary_string);
} }
virtual std::string GetTimestamp() const = 0; virtual std::string GetTimestamp() const = 0;

View File

@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseDataFacade.h" #include "BaseDataFacade.h"
#include "../../DataStructures/Coordinate.h" #include "../../DataStructures/OriginalEdgeData.h"
#include "../../DataStructures/QueryNode.h" #include "../../DataStructures/QueryNode.h"
#include "../../DataStructures/QueryEdge.h" #include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/SharedMemoryVectorWrapper.h" #include "../../DataStructures/SharedMemoryVectorWrapper.h"
@ -40,10 +40,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../DataStructures/StaticRTree.h" #include "../../DataStructures/StaticRTree.h"
#include "../../Util/BoostFileSystemFix.h" #include "../../Util/BoostFileSystemFix.h"
#include "../../Util/GraphLoader.h" #include "../../Util/GraphLoader.h"
#include "../../Util/IniFile.h"
#include "../../Util/ProgramOptions.h" #include "../../Util/ProgramOptions.h"
#include "../../Util/SimpleLogger.h" #include "../../Util/SimpleLogger.h"
#include <osrm/Coordinate.h>
template<class EdgeDataT> template<class EdgeDataT>
class InternalDataFacade : public BaseDataFacade<EdgeDataT> { class InternalDataFacade : public BaseDataFacade<EdgeDataT> {
@ -155,9 +156,9 @@ private:
(char*)&(current_edge_data), (char*)&(current_edge_data),
sizeof(OriginalEdgeData) sizeof(OriginalEdgeData)
); );
m_via_node_list[i] = current_edge_data.viaNode; m_via_node_list[i] = current_edge_data.via_node;
m_name_ID_list[i] = current_edge_data.nameID; m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turnInstruction; m_turn_instruction_list[i] = current_edge_data.turn_instruction;
} }
edges_input_stream.close(); edges_input_stream.close();
} }

View File

@ -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_mutex.hpp>
#include <boost/interprocess/sync/named_condition.hpp> #include <boost/interprocess/sync/named_condition.hpp>
@ -38,3 +68,5 @@ struct SharedBarriers {
// Is there any query? // Is there any query?
int number_of_queries; int number_of_queries;
}; };
#endif //SHARED_BARRIER_H

View File

@ -356,14 +356,14 @@ public:
name_id < m_name_begin_indices.size(), name_id < m_name_begin_indices.size(),
"name id too high" "name id too high"
); );
unsigned begin_index = m_name_begin_indices[name_id]; const unsigned begin_index = m_name_begin_indices[name_id];
unsigned end_index = m_name_begin_indices[name_id+1]; const unsigned end_index = m_name_begin_indices[name_id+1];
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
begin_index < m_names_char_list.size(), begin_index <= m_names_char_list.size(),
"begin index of name too high" "begin index of name too high"
); );
BOOST_ASSERT_MSG( BOOST_ASSERT_MSG(
end_index < m_names_char_list.size(), end_index <= m_names_char_list.size(),
"end index of name too high" "end index of name too high"
); );

View File

@ -31,7 +31,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseDataFacade.h" #include "BaseDataFacade.h"
#include "../../DataStructures/Coordinate.h"
#include "../../DataStructures/QueryEdge.h" #include "../../DataStructures/QueryEdge.h"
#include "../../DataStructures/StaticGraph.h" #include "../../DataStructures/StaticGraph.h"
#include "../../DataStructures/StaticRTree.h" #include "../../DataStructures/StaticRTree.h"
@ -39,6 +38,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../../typedefs.h" #include "../../typedefs.h"
#include <osrm/Coordinate.h>
#include <boost/integer.hpp> #include <boost/integer.hpp>
typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf; typedef BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf RTreeLeaf;

View File

@ -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 { 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> Reply::toBuffers(){
std::vector<boost::asio::const_buffer> buffers; std::vector<boost::asio::const_buffer> buffers;
buffers.push_back(ToBuffer(status)); buffers.push_back(ToBuffer(status));
@ -88,25 +104,27 @@ Reply Reply::StockReply(Reply::status_type status) {
} }
std::string Reply::ToString(Reply::status_type status) { std::string Reply::ToString(Reply::status_type status) {
switch (status) { if (Reply::ok == status)
case Reply::ok: {
return okHTML; 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) { boost::asio::const_buffer Reply::ToBuffer(Reply::status_type status) {
switch (status) { if (Reply::ok == status)
case Reply::ok: {
return boost::asio::buffer(okString); 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
View 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(&ltime);
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("&nbsp;");
}
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;
}

View File

@ -28,95 +28,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef REQUEST_HANDLER_H #ifndef REQUEST_HANDLER_H
#define REQUEST_HANDLER_H #define REQUEST_HANDLER_H
#include "APIGrammar.h"
#include "DataStructures/RouteParameters.h"
#include "Http/Request.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 <boost/noncopyable.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string> #include <string>
template <typename Iterator, class HandlerT>
struct APIGrammar;
struct RouteParameters;
class OSRM;
class RequestHandler : private boost::noncopyable { class RequestHandler : private boost::noncopyable {
public: public:
typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser; typedef APIGrammar<std::string::iterator, RouteParameters> APIGrammarParser;
explicit RequestHandler() : routing_machine(NULL) { }
void handle_request(const http::Request& req, http::Reply& rep){ RequestHandler();
//parse command
try {
std::string request(req.uri);
time_t ltime; void handle_request(const http::Request& req, http::Reply& rep);
struct tm *Tm; void RegisterRoutingMachine(OSRM * osrm);
ltime=time(NULL);
Tm=localtime(&ltime);
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("&nbsp;");
}
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;
}
private: private:
OSRM * routing_machine; OSRM * routing_machine;

View File

@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "Http/Request.h"
#include "RequestParser.h" #include "RequestParser.h"
namespace http { namespace http {

View File

@ -29,14 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define REQUEST_PARSER_H #define REQUEST_PARSER_H
#include "Http/CompressionType.h" #include "Http/CompressionType.h"
#include "Http/Header.h" #include <osrm/Header.h>
#include "Http/Request.h"
#include <boost/logic/tribool.hpp> #include <boost/logic/tribool.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
namespace http { namespace http {
struct Request;
class RequestParser { class RequestParser {
public: public:
RequestParser(); RequestParser();

View File

@ -29,23 +29,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define SERVERFACTORY_H_ #define SERVERFACTORY_H_
#include "Server.h" #include "Server.h"
#include "../Util/OpenMPWrapper.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include <zlib.h> #include <zlib.h>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <sstream>
struct ServerFactory : boost::noncopyable { 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() << SimpleLogger().Write() <<
"http 1.1 compression handled by zlib version " << zlibVersion(); "http 1.1 compression handled by zlib version " << zlibVersion();
std::stringstream port_stream; std::string port_stream;
port_stream << ip_port; intToString(ip_port, port_stream);
return new Server( ip_address, port_stream.str(), std::min( omp_get_num_procs(), threads) );
return new Server(
ip_address,
port_stream,
std::min( omp_get_num_procs(), threads )
);
} }
}; };

View File

@ -79,6 +79,11 @@ int main (int argc, char * argv[]) {
"starting up engines, " << g_GIT_DESCRIPTION << ", " << "starting up engines, " << g_GIT_DESCRIPTION << ", " <<
"compiled at " << __DATE__ << ", " __TIME__; "compiled at " << __DATE__ << ", " __TIME__;
#ifdef __FreeBSD__
SimpleLogger().Write() << "Not supported on FreeBSD";
return 0;
#endif
if( 1 == argc ) { if( 1 == argc ) {
SimpleLogger().Write(logWARNING) << SimpleLogger().Write(logWARNING) <<
"usage: " << argv[0] << " /path/on/device"; "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 ret1 = fseek(fd, current_offset, SEEK_SET);
int ret2 = read(fileno(fd), (char*)&single_block[0], 4096); int ret2 = read(fileno(fd), (char*)&single_block[0], 4096);
#endif #endif
#ifdef __FreeBSD__
int ret1 = 0;
int ret2 = 0;
#endif
#ifdef __linux__ #ifdef __linux__
int ret1 = lseek(f, current_offset, SEEK_SET); int ret1 = lseek(f, current_offset, SEEK_SET);
int ret2 = read(f, (char*)single_block, 4096); 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 ret1 = fseek(fd, current_offset, SEEK_SET);
int ret2 = read(fileno(fd), (char*)&single_block, 4096); int ret2 = read(fileno(fd), (char*)&single_block, 4096);
#endif #endif
#ifdef __FreeBSD__
int ret1 = 0;
int ret2 = 0;
#endif
#ifdef __linux__ #ifdef __linux__
int ret1 = lseek(f, current_offset, SEEK_SET); int ret1 = lseek(f, current_offset, SEEK_SET);

View File

@ -26,8 +26,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "../Library/OSRM.h" #include "../Library/OSRM.h"
#include "../Util/GitDescription.h"
#include "../Util/ProgramOptions.h"
#include "../Util/SimpleLogger.h" #include "../Util/SimpleLogger.h"
#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
@ -37,15 +40,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream> #include <sstream>
//Dude, real recursions on the OS stack? You must be brave... //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(); boost::property_tree::ptree::const_iterator end = property_tree.end();
for (boost::property_tree::ptree::const_iterator it = pt.begin(); it != end; ++it) { for (boost::property_tree::ptree::const_iterator tree_iterator = property_tree.begin(); tree_iterator != end; ++tree_iterator)
for(unsigned i = 0; i < recursion_depth; ++i) { {
for (unsigned current_recursion = 0; current_recursion < recursion_depth; ++current_recursion)
{
std::cout << " " << std::flush; std::cout << " " << std::flush;
} }
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl; std::cout << tree_iterator->first << ": " << tree_iterator->second.get_value<std::string>() << std::endl;
print_tree(it->second, recursion_depth+1); print_tree(tree_iterator->second, recursion_depth+1);
} }
} }
@ -54,8 +59,8 @@ int main (int argc, const char * argv[]) {
LogPolicy::GetInstance().Unmute(); LogPolicy::GetInstance().Unmute();
try { try {
std::string ip_address; std::string ip_address;
int ip_port, requested_num_threads; int ip_port, requested_thread_num;
bool use_shared_memory = false; bool use_shared_memory = false, trial = false;
ServerPaths server_paths; ServerPaths server_paths;
if( !GenerateServerProgramOptions( if( !GenerateServerProgramOptions(
argc, argc,
@ -63,8 +68,9 @@ int main (int argc, const char * argv[]) {
server_paths, server_paths,
ip_address, ip_address,
ip_port, ip_port,
requested_num_threads, requested_thread_num,
use_shared_memory use_shared_memory,
trial
) )
) { ) {
return 0; return 0;
@ -100,19 +106,20 @@ int main (int argc, const char * argv[]) {
//attention: super-inefficient hack below: //attention: super-inefficient hack below:
std::stringstream ss; std::stringstream my_stream;
BOOST_FOREACH(const std::string & line, osrm_reply.content) { BOOST_FOREACH(const std::string & line, osrm_reply.content)
{
std::cout << line; std::cout << line;
ss << line; my_stream << line;
} }
std::cout << std::endl; std::cout << std::endl;
boost::property_tree::ptree pt; boost::property_tree::ptree property_tree;
boost::property_tree::read_json(ss, pt); boost::property_tree::read_json(my_stream, property_tree);
print_tree(pt, 0); print_tree(property_tree, 0);
} catch (std::exception & e) { } catch (std::exception & current_exception) {
SimpleLogger().Write(logWARNING) << "caught exception: " << e.what(); SimpleLogger().Write(logWARNING) << "caught exception: " << current_exception.what();
return -1; return -1;
} }
return 0; return 0;

View File

@ -28,15 +28,87 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef BOOST_FILE_SYSTEM_FIX_H #ifndef BOOST_FILE_SYSTEM_FIX_H
#define BOOST_FILE_SYSTEM_FIX_H #define BOOST_FILE_SYSTEM_FIX_H
#include "OSRMException.h"
#include <boost/any.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
//This is one big workaround for latest boost renaming woes. //This is one big workaround for latest boost renaming woes.
#if BOOST_FILESYSTEM_VERSION < 3 #if BOOST_FILESYSTEM_VERSION < 3
#warning Boost Installation with Filesystem3 missing, activating workaround #warning Boost Installation with Filesystem3 missing, activating workaround
#include <cstdio> #include <cstdio>
#endif
namespace boost { namespace boost {
namespace filesystem { 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() { inline path temp_directory_path() {
char * buffer; char * buffer;
buffer = tmpnam (NULL); buffer = tmpnam (NULL);
@ -48,10 +120,9 @@ inline path unique_path(const path&) {
return temp_directory_path(); return temp_directory_path();
} }
}
}
#endif #endif
}
}
#ifndef BOOST_FILESYSTEM_VERSION #ifndef BOOST_FILESYSTEM_VERSION
#define BOOST_FILESYSTEM_VERSION 3 #define BOOST_FILESYSTEM_VERSION 3

56
Util/ComputeAngle.h Normal file
View 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

View File

@ -50,5 +50,19 @@ inline void remove_consecutive_duplicates_from_vector(std::vector<T> & vector) {
vector.resize(number_of_unique_elements); 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_ */ #endif /* CONTAINERUTILS_H_ */

336
Util/DataStoreOptions.h Normal file
View 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 */

View File

@ -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[]; extern char g_GIT_DESCRIPTION[];
#endif //GIT_DESCRIPTION_H

100
Util/IniFile.cpp Normal file
View 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);
}
}

View File

@ -28,82 +28,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INI_FILE_H_ #ifndef INI_FILE_H_
#define INI_FILE_H_ #define INI_FILE_H_
#include "OSRMException.h"
#include "../DataStructures/HashTable.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 <string>
#include <vector>
class IniFile { class IniFile {
public: public:
IniFile(const char * config_filename) { 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 GetParameter(const std::string & key);
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) const;
return parameters.Find(key);
}
std::string GetParameter(const std::string & key) const { bool Holds(const std::string & key) const;
return parameters.Find(key);
}
bool Holds(const std::string & key) const { void SetParameter(const char* key, const char* value);
return parameters.Holds(key);
}
void SetParameter(const char* key, const char* value) { void SetParameter(const std::string & key, const std::string & value);
SetParameter(std::string(key), std::string(value));
}
void SetParameter(const std::string & key, const std::string & value) {
parameters.insert(std::make_pair(key, value));
}
private: private:
void Tokenize( void Tokenize(
const std::string& str, const std::string& str,
std::vector<std::string>& tokens, std::vector<std::string>& tokens,
const std::string& delimiters = "=" 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; HashTable<std::string, std::string> parameters;
}; };

View File

@ -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_ */

View File

@ -28,15 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef MACHINE_INFO_H #ifndef MACHINE_INFO_H
#define 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 { enum Endianness {
LittleEndian = 1, LittleEndian = 1,
BigEndian = 2 BigEndian = 2
@ -46,8 +37,9 @@ enum Endianness {
inline Endianness getMachineEndianness() { inline Endianness getMachineEndianness() {
int i(1); int i(1);
char *p = (char *) &i; char *p = (char *) &i;
if (1 == p[0]) if (1 == p[0]) {
return LittleEndian; return LittleEndian;
}
return BigEndian; return BigEndian;
} }
@ -58,36 +50,4 @@ inline unsigned swapEndian(unsigned x) {
return 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 #endif // MACHINE_INFO_H

View File

@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "OSRMException.h" #include "OSRMException.h"
#include "SimpleLogger.h" #include "SimpleLogger.h"
#include <osrm/ServerPaths.h>
#include <boost/any.hpp> #include <boost/any.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
@ -40,36 +42,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <vector>
typedef boost::unordered_map< const static unsigned INIT_OK_START_ENGINE = 0;
const std::string, const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1;
boost::filesystem::path const static unsigned INIT_FAILED = -1;
> 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");
}
}
}
}
// support old capitalized option names by down-casing them with a regex replace // support old capitalized option names by down-casing them with a regex replace
inline void PrepareConfigFile( inline void PrepareConfigFile(
@ -86,16 +62,16 @@ inline void PrepareConfigFile(
output = boost::regex_replace( input_str, regex, format ); output = boost::regex_replace( input_str, regex, format );
} }
// generate boost::program_options object for the routing part // generate boost::program_options object for the routing part
inline bool GenerateServerProgramOptions( inline unsigned GenerateServerProgramOptions(
const int argc, const int argc,
const char * argv[], const char * argv[],
ServerPaths & paths, ServerPaths & paths,
std::string & ip_address, std::string & ip_address,
int & ip_port, int & ip_port,
int & requested_num_threads, int & requested_num_threads,
bool & use_shared_memory bool & use_shared_memory,
bool & trial
) { ) {
// declare a group of options that will be allowed only on command line // declare a group of options that will be allowed only on command line
@ -109,6 +85,11 @@ inline bool GenerateServerProgramOptions(
&paths["config"] &paths["config"]
)->default_value("server.ini"), )->default_value("server.ini"),
"Path to a configuration file" "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 // declare a group of options that will be allowed both on command line
@ -162,7 +143,7 @@ inline bool GenerateServerProgramOptions(
) )
( (
"sharedmemory,s", "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" "Load data from shared memory"
); );
@ -201,12 +182,12 @@ inline bool GenerateServerProgramOptions(
if(option_variables.count("version")) { if(option_variables.count("version")) {
SimpleLogger().Write() << g_GIT_DESCRIPTION; SimpleLogger().Write() << g_GIT_DESCRIPTION;
return false; return INIT_OK_DO_NOT_START_ENGINE;
} }
if(option_variables.count("help")) { if(option_variables.count("help")) {
SimpleLogger().Write() << visible_options; SimpleLogger().Write() << visible_options;
return false; return INIT_OK_DO_NOT_START_ENGINE;
} }
boost::program_options::notify(option_variables); boost::program_options::notify(option_variables);
@ -221,7 +202,7 @@ inline bool GenerateServerProgramOptions(
SimpleLogger().Write() << SimpleLogger().Write() <<
"Reading options from: " << path_iterator->second.string(); "Reading options from: " << path_iterator->second.string();
std::string config_str; std::string config_str;
PrepareConfigFile( paths["config"], config_str ); PrepareConfigFile( path_iterator->second, config_str );
std::stringstream config_stream( config_str ); std::stringstream config_stream( config_str );
boost::program_options::store( boost::program_options::store(
parse_config_file(config_stream, config_file_options), parse_config_file(config_stream, config_file_options),
@ -230,14 +211,23 @@ inline bool GenerateServerProgramOptions(
boost::program_options::notify(option_variables); 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") ) { 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"); path_iterator = paths.find("hsgrdata");
if( if(
path_iterator != paths.end() && path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second) !boost::filesystem::is_regular_file(path_iterator->second)
) { ) {
path_iterator->second = base_string + ".hsgr"; path_iterator->second = base_string + ".hsgr";
} else {
throw OSRMException(base_string + ".hsgr not found");
} }
path_iterator = paths.find("nodesdata"); path_iterator = paths.find("nodesdata");
@ -246,38 +236,52 @@ inline bool GenerateServerProgramOptions(
!boost::filesystem::is_regular_file(path_iterator->second) !boost::filesystem::is_regular_file(path_iterator->second)
) { ) {
path_iterator->second = base_string + ".nodes"; path_iterator->second = base_string + ".nodes";
} else {
throw OSRMException(base_string + ".nodes not found");
} }
path_iterator = paths.find("edgesdata"); path_iterator = paths.find("edgesdata");
if( if(
path_iterator != paths.end() && path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second) !boost::filesystem::is_regular_file(path_iterator->second)
) { ) {
path_iterator->second = base_string + ".edges"; path_iterator->second = base_string + ".edges";
} else {
throw OSRMException(base_string + ".edges not found");
} }
path_iterator = paths.find("ramindex"); path_iterator = paths.find("ramindex");
if( if(
path_iterator != paths.end() && path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second) !boost::filesystem::is_regular_file(path_iterator->second)
) { ) {
path_iterator->second = base_string + ".ramIndex"; path_iterator->second = base_string + ".ramIndex";
} else {
throw OSRMException(base_string + ".ramIndex not found");
} }
path_iterator = paths.find("fileindex"); path_iterator = paths.find("fileindex");
if( if(
path_iterator != paths.end() && path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second) !boost::filesystem::is_regular_file(path_iterator->second)
) { ) {
path_iterator->second = base_string + ".fileIndex"; path_iterator->second = base_string + ".fileIndex";
} else {
throw OSRMException(base_string + ".fileIndex not found");
} }
path_iterator = paths.find("namesdata"); path_iterator = paths.find("namesdata");
if( if(
path_iterator != paths.end() && path_iterator != paths.end() &&
!boost::filesystem::is_regular_file(path_iterator->second) !boost::filesystem::is_regular_file(path_iterator->second)
) { ) {
path_iterator->second = base_string + ".names"; path_iterator->second = base_string + ".names";
} else {
throw OSRMException(base_string + ".namesIndex not found");
} }
path_iterator = paths.find("timestamp"); path_iterator = paths.find("timestamp");
@ -287,12 +291,15 @@ inline bool GenerateServerProgramOptions(
) { ) {
path_iterator->second = base_string + ".timestamp"; path_iterator->second = base_string + ".timestamp";
} }
}
if( 1 > requested_num_threads ) { return INIT_OK_START_ENGINE;
throw OSRMException("Number of threads must be a positive number");
} }
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 */ #endif /* PROGRAM_OPTIONS_H */

View File

@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/qi.hpp>
#include <cstdio> #include <cstdio>
#include <cctype>
#include <string> #include <string>
// precision: position after decimal point // precision: position after decimal point
@ -159,6 +160,47 @@ inline void stringSplit(
boost::split(result, s, boost::is_any_of(std::string(&delim))); 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 originals[] = {"&", "\"", "<", ">", "'", "[", "]", "\\"};
static std::string entities[] = {"&amp;", "&quot;", "&lt;", "&gt;", "&#39;", "&91;", "&93;", " &#92;" }; static std::string entities[] = {"&amp;", "&quot;", "&lt;", "&gt;", "&#39;", "&91;", "&93;", " &#92;" };
@ -177,6 +219,36 @@ inline std::string HTMLDeEntitize( std::string & result) {
return 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( inline bool StringStartsWith(
const std::string & input, const std::string & input,
const std::string & prefix const std::string & prefix
@ -184,4 +256,18 @@ inline bool StringStartsWith(
return boost::starts_with(input, prefix); 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_ */ #endif /* STRINGUTIL_H_ */

View 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
View 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}

View File

@ -2,7 +2,8 @@
##YAML Template ##YAML Template
--- ---
default: --require features --tags ~@todo --tags ~@bug --tag ~@stress 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 bugs: --require features --tags @bug
todo: --require features --tags @todo todo: --require features --tags @todo
all: --require features all: --require features

View File

@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "DataStructures/OriginalEdgeData.h"
#include "DataStructures/QueryEdge.h" #include "DataStructures/QueryEdge.h"
#include "DataStructures/SharedMemoryFactory.h" #include "DataStructures/SharedMemoryFactory.h"
#include "DataStructures/SharedMemoryVectorWrapper.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/SharedDataType.h"
#include "Server/DataStructures/SharedBarriers.h" #include "Server/DataStructures/SharedBarriers.h"
#include "Util/BoostFileSystemFix.h" #include "Util/BoostFileSystemFix.h"
#include "Util/ProgramOptions.h" #include "Util/DataStoreOptions.h"
#include "Util/SimpleLogger.h" #include "Util/SimpleLogger.h"
#include "Util/UUID.h" #include "Util/UUID.h"
#include "typedefs.h" #include "typedefs.h"
@ -50,8 +51,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
int main( const int argc, const char * argv[] ) { int main( const int argc, const char * argv[] ) {
SharedBarriers barrier;
LogPolicy::GetInstance().Unmute();
SharedBarriers barrier;
#ifdef __linux__ #ifdef __linux__
if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) { if( -1 == mlockall(MCL_CURRENT | MCL_FUTURE) ) {
@ -61,31 +63,27 @@ int main( const int argc, const char * argv[] ) {
#endif #endif
try { try {
boost::interprocess::scoped_lock< try {
boost::interprocess::named_mutex boost::interprocess::scoped_lock<
> pending_lock(barrier.pending_update_mutex); boost::interprocess::named_mutex
} catch(...) { > pending_lock(barrier.pending_update_mutex);
// hard unlock in case of any exception. } catch(...) {
barrier.pending_update_mutex.unlock(); // hard unlock in case of any exception.
barrier.pending_update_mutex.unlock();
}
} catch(const std::exception & e) {
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
} }
try {
LogPolicy::GetInstance().Unmute();
SimpleLogger().Write(logDEBUG) << "Checking input parameters";
bool use_shared_memory = false; try {
std::string ip_address; SimpleLogger().Write(logDEBUG) << "Checking input parameters";
int ip_port, requested_num_threads;
ServerPaths server_paths; ServerPaths server_paths;
if( if(
!GenerateServerProgramOptions( !GenerateDataStoreOptions(
argc, argc,
argv, argv,
server_paths, server_paths
ip_address,
ip_port,
requested_num_threads,
use_shared_memory
) )
) { ) {
return 0; return 0;
@ -124,7 +122,8 @@ int main( const int argc, const char * argv[] ) {
paths_iterator = server_paths.find("fileindex"); paths_iterator = server_paths.find("fileindex");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty()); 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"); paths_iterator = server_paths.find("nodesdata");
BOOST_ASSERT(server_paths.end() != paths_iterator); BOOST_ASSERT(server_paths.end() != paths_iterator);
BOOST_ASSERT(!paths_iterator->second.empty()); 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 shared_layout_ptr->ram_index_file_name
); );
// add zero termination // 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'; shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0';
// collect number of elements to store in shared memory object // 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), (char*)&(current_edge_data),
sizeof(OriginalEdgeData) sizeof(OriginalEdgeData)
); );
via_node_ptr[i] = current_edge_data.viaNode; via_node_ptr[i] = current_edge_data.via_node;
name_id_ptr[i] = current_edge_data.nameID; name_id_ptr[i] = current_edge_data.name_id;
turn_instructions_ptr[i] = current_edge_data.turnInstruction; turn_instructions_ptr[i] = current_edge_data.turn_instruction;
} }
edges_input_stream.close(); edges_input_stream.close();
@ -379,7 +378,7 @@ int main( const int argc, const char * argv[] ) {
); );
hsgr_input_stream.close(); hsgr_input_stream.close();
//TODO acquire lock // acquire lock
SharedMemory * data_type_memory = SharedMemoryFactory::Get( SharedMemory * data_type_memory = SharedMemoryFactory::Get(
CURRENT_REGIONS, CURRENT_REGIONS,
sizeof(SharedDataTimestamp), sizeof(SharedDataTimestamp),

Some files were not shown because too many files have changed in this diff Show More