Merging develop branch into master for v0.3.4 release
This commit is contained in:
commit
828b370ea1
6
.gitignore
vendored
6
.gitignore
vendored
@ -33,11 +33,9 @@ ehthumbs.db
|
|||||||
Icon?
|
Icon?
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
# SCons related files #
|
# build related files #
|
||||||
#######################
|
#######################
|
||||||
SconsBuilder*
|
/build/
|
||||||
.scon*
|
|
||||||
.build
|
|
||||||
|
|
||||||
# Eclipse related files #
|
# Eclipse related files #
|
||||||
#########################
|
#########################
|
||||||
|
@ -30,7 +30,6 @@ class IteratorbasedCRC32 {
|
|||||||
private:
|
private:
|
||||||
typedef typename ContainerT::iterator ContainerT_iterator;
|
typedef typename ContainerT::iterator ContainerT_iterator;
|
||||||
unsigned crc;
|
unsigned crc;
|
||||||
unsigned slowcrc_table[1<<8];
|
|
||||||
|
|
||||||
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
typedef boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> my_crc_32_type;
|
||||||
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc);
|
||||||
|
111
CMakeLists.txt
Normal file
111
CMakeLists.txt
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.6)
|
||||||
|
project(OSRM)
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||||
|
set(BOOST_COMPONENTS filesystem regex system thread)
|
||||||
|
|
||||||
|
file(GLOB ExtractorGlob Extractor/*.cpp)
|
||||||
|
set(ExtractorSources extractor.cpp ${ExtractorGlob})
|
||||||
|
add_executable(osrm-extract ${ExtractorSources})
|
||||||
|
|
||||||
|
file(GLOB PrepareGlob Contractor/*.cpp)
|
||||||
|
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
|
||||||
|
add_executable(osrm-prepare ${PrepareSources})
|
||||||
|
|
||||||
|
file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp DataStructures/SearchEngine*.cpp)
|
||||||
|
set(RoutedSources routed.cpp ${RoutedGlob})
|
||||||
|
add_executable(osrm-routed ${RoutedSources})
|
||||||
|
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||||
|
|
||||||
|
# Check the release mode
|
||||||
|
if(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif(NOT CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
message(STATUS "Configuring OSRM in debug mode")
|
||||||
|
endif(CMAKE_BUILD_TYPE MATCHES Debug)
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
message(STATUS "Configuring OSRM in release mode")
|
||||||
|
endif(CMAKE_BUILD_TYPE MATCHES Release)
|
||||||
|
|
||||||
|
#Configuring compilers
|
||||||
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
# using Clang
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration")
|
||||||
|
message(STATUS "OpenMP parallelization not available using clang++")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
# using GCC
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wall -fopenmp -pedantic")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
|
||||||
|
# using Intel C++
|
||||||
|
set(CMAKE_CXX_FLAGS "-static-intel -wd10237 -Wall -openmp -ipo")
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||||
|
# using Visual Studio C++
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
SET(CMAKE_OSX_ARCHITECTURES "x86_64")
|
||||||
|
message("Set Architecture to x64 on OS X")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#Check Boost
|
||||||
|
set(BOOST_MIN_VERSION "1.44.0")
|
||||||
|
find_package( Boost ${BOOST_MIN_VERSION} COMPONENTS ${BOOST_COMPONENTS} REQUIRED )
|
||||||
|
if (NOT Boost_FOUND)
|
||||||
|
message(FATAL_ERROR "Fatal error: Boost (version >= 1.44.0) required.\n")
|
||||||
|
endif (NOT Boost_FOUND)
|
||||||
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
target_link_libraries( osrm-extract ${Boost_LIBRARIES} )
|
||||||
|
target_link_libraries( osrm-prepare ${Boost_LIBRARIES} )
|
||||||
|
target_link_libraries( osrm-routed ${Boost_LIBRARIES} )
|
||||||
|
|
||||||
|
find_package ( BZip2 REQUIRED )
|
||||||
|
include_directories(${BZIP_INCLUDE_DIRS})
|
||||||
|
target_link_libraries (osrm-extract ${BZIP2_LIBRARIES})
|
||||||
|
|
||||||
|
find_package( ZLIB REQUIRED )
|
||||||
|
target_link_libraries (osrm-extract ${ZLIB_LIBRARY})
|
||||||
|
target_link_libraries (osrm-routed ${ZLIB_LIBRARY})
|
||||||
|
|
||||||
|
find_package( Threads REQUIRED )
|
||||||
|
target_link_libraries (osrm-extract ${Threads_LIBRARY})
|
||||||
|
|
||||||
|
find_package( Lua51 REQUIRED )
|
||||||
|
include_directories(${LUA_INCLUDE_DIR})
|
||||||
|
target_link_libraries( osrm-extract ${LUA_LIBRARY} )
|
||||||
|
target_link_libraries( osrm-prepare ${LUA_LIBRARY} )
|
||||||
|
|
||||||
|
find_package( LibXml2 REQUIRED )
|
||||||
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${LIBXML2_LIBRARIES})
|
||||||
|
|
||||||
|
find_package( Luabind REQUIRED )
|
||||||
|
include_directories(${LUABIND_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${LUABIND_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${LUABIND_LIBRARY})
|
||||||
|
|
||||||
|
find_package( Protobuf REQUIRED )
|
||||||
|
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||||
|
target_link_libraries (osrm-extract ${PROTOBUF_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${PROTOBUF_LIBRARY})
|
||||||
|
|
||||||
|
find_package( STXXL REQUIRED )
|
||||||
|
include_directories(${STXXL_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${STXXL_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${STXXL_LIBRARY})
|
||||||
|
|
||||||
|
find_package( OSMPBF REQUIRED )
|
||||||
|
include_directories(${OSMPBF_INCLUDE_DIR})
|
||||||
|
target_link_libraries (osrm-extract ${OSMPBF_LIBRARY})
|
||||||
|
target_link_libraries (osrm-prepare ${OSMPBF_LIBRARY})
|
||||||
|
|
||||||
|
if(WITH_TOOLS)
|
||||||
|
message("-- Activating OSRM internal tools")
|
||||||
|
find_package( GDAL )
|
||||||
|
if(GDAL_FOUND)
|
||||||
|
add_executable(osrm-components Tools/componentAnalysis.cpp)
|
||||||
|
include_directories(${GDAL_INCLUDE_DIR})
|
||||||
|
target_link_libraries( osrm-components ${GDAL_LIBRARIES} )
|
||||||
|
target_link_libraries( osrm-components ${Boost_LIBRARIES} )
|
||||||
|
endif(GDAL_FOUND)
|
||||||
|
endif(WITH_TOOLS)
|
@ -20,17 +20,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#ifndef CONTRACTOR_H_INCLUDED
|
#ifndef CONTRACTOR_H_INCLUDED
|
||||||
#define CONTRACTOR_H_INCLUDED
|
#define CONTRACTOR_H_INCLUDED
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <cfloat>
|
|
||||||
#include <ctime>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/lambda/lambda.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
#include "TemporaryStorage.h"
|
#include "TemporaryStorage.h"
|
||||||
#include "../DataStructures/BinaryHeap.h"
|
#include "../DataStructures/BinaryHeap.h"
|
||||||
@ -42,6 +31,19 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../Util/OpenMPWrapper.h"
|
#include "../Util/OpenMPWrapper.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/lambda/lambda.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
#include <cfloat>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Contractor {
|
class Contractor {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -119,7 +121,7 @@ public:
|
|||||||
newEdge.target = diter->target();
|
newEdge.target = diter->target();
|
||||||
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
newEdge.data = _ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward());
|
||||||
|
|
||||||
assert( newEdge.data.distance > 0 );
|
BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" );
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) {
|
||||||
WARN("Edge weight large -> " << newEdge.data.distance);
|
WARN("Edge weight large -> " << newEdge.data.distance);
|
||||||
@ -232,8 +234,9 @@ public:
|
|||||||
|
|
||||||
//initialize the variables
|
//initialize the variables
|
||||||
#pragma omp parallel for schedule ( guided )
|
#pragma omp parallel for schedule ( guided )
|
||||||
for ( int x = 0; x < ( int ) numberOfNodes; ++x )
|
for ( int x = 0; x < ( int ) numberOfNodes; ++x ) {
|
||||||
remainingNodes[x].id = x;
|
remainingNodes[x].id = x;
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "initializing elimination PQ ..." << std::flush;
|
std::cout << "initializing elimination PQ ..." << std::flush;
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
@ -247,7 +250,7 @@ public:
|
|||||||
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
|
std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush;
|
||||||
|
|
||||||
bool flushedContractor = false;
|
bool flushedContractor = false;
|
||||||
while ( numberOfContractedNodes < numberOfNodes ) {
|
while ( numberOfNodes > 2 && numberOfContractedNodes < numberOfNodes ) {
|
||||||
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
|
if(!flushedContractor && (numberOfContractedNodes > (numberOfNodes*0.65) ) ){
|
||||||
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
DeallocatingVector<_ContractorEdge> newSetOfEdges; //this one is not explicitely cleared since it goes out of scope anywa
|
||||||
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
std::cout << " [flush " << numberOfContractedNodes << " nodes] " << std::flush;
|
||||||
@ -282,7 +285,6 @@ public:
|
|||||||
|
|
||||||
//walk over all nodes
|
//walk over all nodes
|
||||||
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
for(unsigned i = 0; i < _graph->GetNumberOfNodes(); ++i) {
|
||||||
//INFO("Restructuring node " << i << "|" << _graph->GetNumberOfNodes());
|
|
||||||
const NodeID start = i;
|
const NodeID start = i;
|
||||||
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
|
for(_DynamicGraph::EdgeIterator currentEdge = _graph->BeginEdges(start); currentEdge < _graph->EndEdges(start); ++currentEdge) {
|
||||||
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
|
_DynamicGraph::EdgeData & data = _graph->GetEdgeData(currentEdge);
|
||||||
@ -301,8 +303,14 @@ public:
|
|||||||
newEdge.target = newNodeIDFromOldNodeIDMap[target];
|
newEdge.target = newNodeIDFromOldNodeIDMap[target];
|
||||||
newEdge.data = data;
|
newEdge.data = data;
|
||||||
newEdge.data.originalViaNodeID = true;
|
newEdge.data.originalViaNodeID = true;
|
||||||
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[start] );
|
BOOST_ASSERT_MSG(
|
||||||
assert(UINT_MAX != newNodeIDFromOldNodeIDMap[target]);
|
UINT_MAX != newNodeIDFromOldNodeIDMap[start],
|
||||||
|
"new start id not resolveable"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
UINT_MAX != newNodeIDFromOldNodeIDMap[target],
|
||||||
|
"new target id not resolveable"
|
||||||
|
);
|
||||||
newSetOfEdges.push_back(newEdge);
|
newSetOfEdges.push_back(newEdge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -311,8 +319,6 @@ public:
|
|||||||
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
|
tempStorage.seek(temporaryStorageSlotID, initialFilePosition);
|
||||||
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
tempStorage.writeToSlot(temporaryStorageSlotID, (char*)&numberOfTemporaryEdges, sizeof(unsigned));
|
||||||
|
|
||||||
// INFO("Flushed " << numberOfTemporaryEdges << " edges to disk");
|
|
||||||
|
|
||||||
//Delete map from old NodeIDs to new ones.
|
//Delete map from old NodeIDs to new ones.
|
||||||
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
std::vector<NodeID>().swap(newNodeIDFromOldNodeIDMap);
|
||||||
|
|
||||||
@ -438,38 +444,48 @@ public:
|
|||||||
Percent p (_graph->GetNumberOfNodes());
|
Percent p (_graph->GetNumberOfNodes());
|
||||||
INFO("Getting edges of minimized graph");
|
INFO("Getting edges of minimized graph");
|
||||||
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
NodeID numberOfNodes = _graph->GetNumberOfNodes();
|
||||||
if(oldNodeIDFromNewNodeIDMap.size()) {
|
if(_graph->GetNumberOfNodes()) {
|
||||||
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
for ( NodeID node = 0; node < numberOfNodes; ++node ) {
|
||||||
p.printStatus(node);
|
p.printStatus(node);
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge < endEdges; ++edge ) {
|
||||||
const NodeID target = _graph->GetTarget( edge );
|
const NodeID target = _graph->GetTarget( edge );
|
||||||
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
const _DynamicGraph::EdgeData& data = _graph->GetEdgeData( edge );
|
||||||
Edge newEdge;
|
Edge newEdge;
|
||||||
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
if(0 != oldNodeIDFromNewNodeIDMap.size()) {
|
||||||
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
newEdge.source = oldNodeIDFromNewNodeIDMap[node];
|
||||||
assert(UINT_MAX != newEdge.source);
|
newEdge.target = oldNodeIDFromNewNodeIDMap[target];
|
||||||
assert(UINT_MAX != newEdge.target);
|
} else {
|
||||||
|
newEdge.source = node;
|
||||||
|
newEdge.target = target;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
UINT_MAX != newEdge.source,
|
||||||
|
"Source id invalid"
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
UINT_MAX != newEdge.target,
|
||||||
|
"Target id invalid"
|
||||||
|
);
|
||||||
newEdge.data.distance = data.distance;
|
newEdge.data.distance = data.distance;
|
||||||
newEdge.data.shortcut = data.shortcut;
|
newEdge.data.shortcut = data.shortcut;
|
||||||
if(!data.originalViaNodeID)
|
if(!data.originalViaNodeID && oldNodeIDFromNewNodeIDMap.size()) {
|
||||||
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
newEdge.data.id = oldNodeIDFromNewNodeIDMap[data.id];
|
||||||
else
|
} else {
|
||||||
newEdge.data.id = data.id;
|
newEdge.data.id = data.id;
|
||||||
|
}
|
||||||
assert(newEdge.data.id != UINT_MAX);
|
BOOST_ASSERT_MSG(
|
||||||
|
newEdge.data.id <= INT_MAX, //2^31
|
||||||
|
"edge id invalid"
|
||||||
|
);
|
||||||
newEdge.data.forward = data.forward;
|
newEdge.data.forward = data.forward;
|
||||||
newEdge.data.backward = data.backward;
|
newEdge.data.backward = data.backward;
|
||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INFO("Renumbered edges of minimized graph, freeing space");
|
|
||||||
_graph.reset();
|
_graph.reset();
|
||||||
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
std::vector<NodeID>().swap(oldNodeIDFromNewNodeIDMap);
|
||||||
INFO("Loading temporary edges");
|
|
||||||
|
|
||||||
// std::ifstream temporaryEdgeStorage(temporaryEdgeStorageFilename.c_str(), std::ios::binary);
|
|
||||||
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
TemporaryStorage & tempStorage = TemporaryStorage::GetInstance();
|
||||||
//Also get the edges from temporary storage
|
//Also get the edges from temporary storage
|
||||||
unsigned numberOfTemporaryEdges = 0;
|
unsigned numberOfTemporaryEdges = 0;
|
||||||
@ -494,7 +510,6 @@ public:
|
|||||||
edges.push_back( newEdge );
|
edges.push_back( newEdge );
|
||||||
}
|
}
|
||||||
tempStorage.deallocateSlot(temporaryStorageSlotID);
|
tempStorage.deallocateSlot(temporaryStorageSlotID);
|
||||||
INFO("Hierarchy has " << edges.size() << " edges");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -517,24 +532,27 @@ private:
|
|||||||
|
|
||||||
if ( heap.GetData( node ).target ) {
|
if ( heap.GetData( node ).target ) {
|
||||||
++targetsFound;
|
++targetsFound;
|
||||||
if ( targetsFound >= numTargets )
|
if ( targetsFound >= numTargets ) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//iterate over all edges of node
|
//iterate over all edges of node
|
||||||
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
|
for ( _DynamicGraph::EdgeIterator edge = _graph->BeginEdges( node ), endEdges = _graph->EndEdges( node ); edge != endEdges; ++edge ) {
|
||||||
const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
|
const _ContractorEdgeData& data = _graph->GetEdgeData( edge );
|
||||||
if ( !data.forward )
|
if ( !data.forward ){
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const NodeID to = _graph->GetTarget( edge );
|
const NodeID to = _graph->GetTarget( edge );
|
||||||
if(middleNode == to)
|
if(middleNode == to) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const int toDistance = distance + data.distance;
|
const int toDistance = distance + data.distance;
|
||||||
|
|
||||||
//New Node discovered -> Add to Heap + Node Info Storage
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !heap.WasInserted( to ) )
|
if ( !heap.WasInserted( to ) ) {
|
||||||
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
|
heap.Insert( to, toDistance, _HeapData(currentHop, false) );
|
||||||
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < heap.GetKey( to ) ) {
|
else if ( toDistance < heap.GetKey( to ) ) {
|
||||||
heap.DecreaseKey( to, toDistance );
|
heap.DecreaseKey( to, toDistance );
|
||||||
@ -584,8 +602,9 @@ private:
|
|||||||
|
|
||||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
||||||
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||||
if ( !outData.forward )
|
if ( !outData.forward ) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const NodeID target = _graph->GetTarget( outEdge );
|
const NodeID target = _graph->GetTarget( outEdge );
|
||||||
const int pathDistance = inData.distance + outData.distance;
|
const int pathDistance = inData.distance + outData.distance;
|
||||||
maxDistance = std::max( maxDistance, pathDistance );
|
maxDistance = std::max( maxDistance, pathDistance );
|
||||||
@ -595,15 +614,16 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Simulate )
|
if( Simulate ) {
|
||||||
_Dijkstra( maxDistance, numTargets, 1000, data, node );
|
_Dijkstra( maxDistance, numTargets, 1000, data, node );
|
||||||
else
|
} else {
|
||||||
_Dijkstra( maxDistance, numTargets, 2000, data, node );
|
_Dijkstra( maxDistance, numTargets, 2000, data, node );
|
||||||
|
}
|
||||||
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
for ( _DynamicGraph::EdgeIterator outEdge = _graph->BeginEdges( node ), endOutEdges = _graph->EndEdges( node ); outEdge != endOutEdges; ++outEdge ) {
|
||||||
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
const _ContractorEdgeData& outData = _graph->GetEdgeData( outEdge );
|
||||||
if ( !outData.forward )
|
if ( !outData.forward ) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
const NodeID target = _graph->GetTarget( outEdge );
|
const NodeID target = _graph->GetTarget( outEdge );
|
||||||
const int pathDistance = inData.distance + outData.distance;
|
const int pathDistance = inData.distance + outData.distance;
|
||||||
const int distance = heap.GetKey( target );
|
const int distance = heap.GetKey( target );
|
||||||
@ -643,8 +663,9 @@ private:
|
|||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( !found )
|
if ( !found ) {
|
||||||
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
|
insertedEdges[insertedEdgesSize++] = insertedEdges[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
insertedEdges.resize( insertedEdgesSize );
|
insertedEdges.resize( insertedEdgesSize );
|
||||||
}
|
}
|
||||||
|
@ -89,11 +89,14 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdg
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
|
void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector< EdgeBasedEdge >& outputEdgeList ) {
|
||||||
GUARANTEE(0 == outputEdgeList.size(), "Vector passed to EdgeBasedGraphFactory::GetEdgeBasedEdges(..) is not empty");
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == outputEdgeList.size(),
|
||||||
|
"Vector is not empty"
|
||||||
|
);
|
||||||
edgeBasedEdges.swap(outputEdgeList);
|
edgeBasedEdges.swap(outputEdgeList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdgeBasedGraphFactory::GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes) {
|
void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector<EdgeBasedNode> & nodes) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
|
BOOST_FOREACH(EdgeBasedNode & node, edgeBasedNodes){
|
||||||
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
assert(node.lat1 != INT_MAX); assert(node.lon1 != INT_MAX);
|
||||||
@ -282,7 +285,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State
|
|||||||
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
|
// turnInstruction |= TurnInstructions.AccessRestrictionFlag;
|
||||||
// }
|
// }
|
||||||
distance += penalty;
|
distance += penalty;
|
||||||
|
|
||||||
|
|
||||||
//distance += heightPenalty;
|
//distance += heightPenalty;
|
||||||
//distance += ComputeTurnPenalty(u, v, w);
|
//distance += ComputeTurnPenalty(u, v, w);
|
||||||
@ -328,7 +331,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State
|
|||||||
|
|
||||||
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const {
|
TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const {
|
||||||
const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
|
const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]);
|
||||||
|
|
||||||
if( speedProfile.has_turn_penalty_function ) {
|
if( speedProfile.has_turn_penalty_function ) {
|
||||||
try {
|
try {
|
||||||
//call lua profile to compute turn penalty
|
//call lua profile to compute turn penalty
|
||||||
@ -340,7 +343,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID
|
|||||||
} else {
|
} else {
|
||||||
penalty = 0;
|
penalty = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(u == w) {
|
if(u == w) {
|
||||||
return TurnInstructions.UTurn;
|
return TurnInstructions.UTurn;
|
||||||
}
|
}
|
||||||
|
@ -25,20 +25,6 @@
|
|||||||
#ifndef EDGEBASEDGRAPHFACTORY_H_
|
#ifndef EDGEBASEDGRAPHFACTORY_H_
|
||||||
#define EDGEBASEDGRAPHFACTORY_H_
|
#define EDGEBASEDGRAPHFACTORY_H_
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
#include <stxxl.h>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/unordered_set.hpp>
|
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
#include "../DataStructures/DynamicGraph.h"
|
#include "../DataStructures/DynamicGraph.h"
|
||||||
@ -50,14 +36,22 @@
|
|||||||
#include "../DataStructures/Percent.h"
|
#include "../DataStructures/Percent.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
#include "../Util/BaseConfiguration.h"
|
#include "../Util/BaseConfiguration.h"
|
||||||
|
#include "../Util/LuaUtil.h"
|
||||||
|
|
||||||
extern "C" {
|
#include <stxxl.h>
|
||||||
#include <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
}
|
|
||||||
#include <luabind/luabind.hpp>
|
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include <boost/unordered_set.hpp>
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class EdgeBasedGraphFactory : boost::noncopyable {
|
class EdgeBasedGraphFactory : boost::noncopyable {
|
||||||
public:
|
public:
|
||||||
@ -65,9 +59,23 @@ public:
|
|||||||
bool operator<(const EdgeBasedNode & other) const {
|
bool operator<(const EdgeBasedNode & other) const {
|
||||||
return other.id < id;
|
return other.id < id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const EdgeBasedNode & other) const {
|
bool operator==(const EdgeBasedNode & other) const {
|
||||||
return id == other.id;
|
return id == other.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline _Coordinate Centroid() const {
|
||||||
|
_Coordinate centroid;
|
||||||
|
//The coordinates of the midpoint are given by:
|
||||||
|
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
|
centroid.lon = (std::min(lon1, lon2) + std::max(lon1, lon2))/2;
|
||||||
|
centroid.lat = (std::min(lat1, lat2) + std::max(lat1, lat2))/2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isIgnored() const {
|
||||||
|
return ignoreInGrid;
|
||||||
|
}
|
||||||
NodeID id;
|
NodeID id;
|
||||||
int lat1;
|
int lat1;
|
||||||
int lat2;
|
int lat2;
|
||||||
@ -127,7 +135,7 @@ private:
|
|||||||
RestrictionMap _restrictionMap;
|
RestrictionMap _restrictionMap;
|
||||||
|
|
||||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
|
DeallocatingVector<EdgeBasedEdge> edgeBasedEdges;
|
||||||
DeallocatingVector<EdgeBasedNode> edgeBasedNodes;
|
std::vector<EdgeBasedNode> edgeBasedNodes;
|
||||||
|
|
||||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||||
@ -145,7 +153,7 @@ 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( DeallocatingVector< EdgeBasedNode> & nodes);
|
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||||
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
|
void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData);
|
||||||
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const;
|
TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const;
|
||||||
unsigned GetNumberOfNodes() const;
|
unsigned GetNumberOfNodes() const;
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
//This is one big workaround for latest boost renaming woes.
|
//This is one big workaround for latest boost renaming woes.
|
||||||
|
|
||||||
#ifndef BOOST_FILESYSTEM_VERSION
|
#if BOOST_FILESYSTEM_VERSION < 3
|
||||||
#warning Boost Installation with Filesystem3 (>=1.44) is required, activating workaround
|
#warning Boost Installation with Filesystem3 missing, activating workaround
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace filesystem {
|
namespace filesystem {
|
||||||
@ -54,8 +54,9 @@ inline path unique_path(const path&) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BOOST_FILESYSTEM_VERSION
|
||||||
#define BOOST_FILESYSTEM_VERSION 3
|
#define BOOST_FILESYSTEM_VERSION 3
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* This class implements a singleton file storage for temporary data.
|
* This class implements a singleton file storage for temporary data.
|
||||||
* temporary slots can be accessed by other objects through an int
|
* temporary slots can be accessed by other objects through an int
|
||||||
@ -89,8 +90,6 @@ private:
|
|||||||
}
|
}
|
||||||
void abort(boost::filesystem::filesystem_error& e);
|
void abort(boost::filesystem::filesystem_error& e);
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
struct StreamData {
|
struct StreamData {
|
||||||
bool writeMode;
|
bool writeMode;
|
||||||
boost::filesystem::path pathToTemporaryFile;
|
boost::filesystem::path pathToTemporaryFile;
|
||||||
|
@ -21,7 +21,10 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef COORDINATE_H_
|
#ifndef COORDINATE_H_
|
||||||
#define COORDINATE_H_
|
#define COORDINATE_H_
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
struct _Coordinate {
|
struct _Coordinate {
|
||||||
@ -102,5 +105,4 @@ inline double ApproximateDistanceByEuclid(const _Coordinate &c1, const _Coordina
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* COORDINATE_H_ */
|
#endif /* COORDINATE_H_ */
|
||||||
|
@ -21,18 +21,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef DYNAMICGRAPH_H_INCLUDED
|
#ifndef DYNAMICGRAPH_H_INCLUDED
|
||||||
#define DYNAMICGRAPH_H_INCLUDED
|
#define DYNAMICGRAPH_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include "../DataStructures/DeallocatingVector.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
#include "../DataStructures/DeallocatingVector.h"
|
|
||||||
|
|
||||||
template< typename EdgeDataT>
|
template< typename EdgeDataT>
|
||||||
class DynamicGraph {
|
class DynamicGraph {
|
||||||
public:
|
public:
|
||||||
typedef EdgeDataT EdgeData;
|
typedef EdgeDataT EdgeData;
|
||||||
typedef unsigned NodeIterator;
|
typedef uint32_t NodeIterator;
|
||||||
typedef unsigned EdgeIterator;
|
typedef uint32_t EdgeIterator;
|
||||||
|
|
||||||
class InputEdge {
|
class InputEdge {
|
||||||
public:
|
public:
|
||||||
@ -47,16 +50,16 @@ class DynamicGraph {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//Constructs an empty graph with a given number of nodes.
|
//Constructs an empty graph with a given number of nodes.
|
||||||
DynamicGraph( int nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
DynamicGraph( int32_t nodes ) : m_numNodes(nodes), m_numEdges(0) {
|
||||||
m_nodes.reserve( m_numNodes );
|
m_nodes.reserve( m_numNodes );
|
||||||
m_nodes.resize( m_numNodes );
|
m_nodes.resize( m_numNodes );
|
||||||
|
|
||||||
m_edges.reserve( m_numNodes * 1.1 );
|
m_edges.reserve( m_numNodes * 1.1 );
|
||||||
m_edges.resize( m_numNodes );
|
m_edges.resize( m_numNodes );
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class ContainerT>
|
template<class ContainerT>
|
||||||
DynamicGraph( const int nodes, const ContainerT &graph )
|
DynamicGraph( const int32_t nodes, const ContainerT &graph ) {
|
||||||
{
|
|
||||||
m_numNodes = nodes;
|
m_numNodes = nodes;
|
||||||
m_numEdges = ( EdgeIterator ) graph.size();
|
m_numEdges = ( EdgeIterator ) graph.size();
|
||||||
m_nodes.reserve( m_numNodes +1);
|
m_nodes.reserve( m_numNodes +1);
|
||||||
@ -80,7 +83,10 @@ class DynamicGraph {
|
|||||||
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
for ( EdgeIterator i = m_nodes[node].firstEdge, e = m_nodes[node].firstEdge + m_nodes[node].edges; i != e; ++i ) {
|
||||||
m_edges[i].target = graph[edge].target;
|
m_edges[i].target = graph[edge].target;
|
||||||
m_edges[i].data = graph[edge].data;
|
m_edges[i].data = graph[edge].data;
|
||||||
GUARANTEE(graph[edge].data.distance > 0, "edge: " << edge << "(" << graph[edge].source << "," << graph[edge].target << ")=" << graph[edge].data.distance);
|
BOOST_ASSERT_MSG(
|
||||||
|
graph[edge].data.distance > 0,
|
||||||
|
"edge distance invalid"
|
||||||
|
);
|
||||||
++edge;
|
++edge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,17 +94,15 @@ class DynamicGraph {
|
|||||||
|
|
||||||
~DynamicGraph(){ }
|
~DynamicGraph(){ }
|
||||||
|
|
||||||
unsigned GetNumberOfNodes() const
|
uint32_t GetNumberOfNodes() const {
|
||||||
{
|
|
||||||
return m_numNodes;
|
return m_numNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetNumberOfEdges() const
|
uint32_t GetNumberOfEdges() const {
|
||||||
{
|
|
||||||
return m_numEdges;
|
return m_numEdges;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetOutDegree( const NodeIterator n ) const {
|
uint32_t GetOutDegree( const NodeIterator n ) const {
|
||||||
return m_nodes[n].edges;
|
return m_nodes[n].edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +119,6 @@ class DynamicGraph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
EdgeIterator BeginEdges( const NodeIterator n ) const {
|
||||||
//assert( EndEdges( n ) - EdgeIterator( _nodes[n].firstEdge ) <= 100 );
|
|
||||||
return EdgeIterator( m_nodes[n].firstEdge );
|
return EdgeIterator( m_nodes[n].firstEdge );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +136,7 @@ class DynamicGraph {
|
|||||||
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
m_edges[node.firstEdge] = m_edges[node.firstEdge + node.edges];
|
||||||
} else {
|
} else {
|
||||||
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
EdgeIterator newFirstEdge = ( EdgeIterator ) m_edges.size();
|
||||||
unsigned newSize = node.edges * 1.1 + 2;
|
uint32_t newSize = node.edges * 1.1 + 2;
|
||||||
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
EdgeIterator requiredCapacity = newSize + m_edges.size();
|
||||||
EdgeIterator oldCapacity = m_edges.capacity();
|
EdgeIterator oldCapacity = m_edges.capacity();
|
||||||
if ( requiredCapacity >= oldCapacity ) {
|
if ( requiredCapacity >= oldCapacity ) {
|
||||||
@ -162,15 +165,15 @@ class DynamicGraph {
|
|||||||
Node &node = m_nodes[source];
|
Node &node = m_nodes[source];
|
||||||
--m_numEdges;
|
--m_numEdges;
|
||||||
--node.edges;
|
--node.edges;
|
||||||
const unsigned last = node.firstEdge + node.edges;
|
const uint32_t last = node.firstEdge + node.edges;
|
||||||
//swap with last edge
|
//swap with last edge
|
||||||
m_edges[e] = m_edges[last];
|
m_edges[e] = m_edges[last];
|
||||||
makeDummy( last );
|
makeDummy( last );
|
||||||
}
|
}
|
||||||
|
|
||||||
//removes all edges (source,target)
|
//removes all edges (source,target)
|
||||||
int DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
|
int32_t DeleteEdgesTo( const NodeIterator source, const NodeIterator target ) {
|
||||||
int deleted = 0;
|
int32_t deleted = 0;
|
||||||
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
for ( EdgeIterator i = BeginEdges( source ), iend = EndEdges( source ); i < iend - deleted; ++i ) {
|
||||||
if ( m_edges[i].target == target ) {
|
if ( m_edges[i].target == target ) {
|
||||||
do {
|
do {
|
||||||
@ -200,11 +203,11 @@ class DynamicGraph {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool isDummy( EdgeIterator edge ) const {
|
bool isDummy( const EdgeIterator edge ) const {
|
||||||
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
|
return m_edges[edge].target == (std::numeric_limits< NodeIterator >::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeDummy( EdgeIterator edge ) {
|
void makeDummy( const EdgeIterator edge ) {
|
||||||
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
|
m_edges[edge].target = (std::numeric_limits< NodeIterator >::max)();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +215,7 @@ class DynamicGraph {
|
|||||||
//index of the first edge
|
//index of the first edge
|
||||||
EdgeIterator firstEdge;
|
EdgeIterator firstEdge;
|
||||||
//amount of edges
|
//amount of edges
|
||||||
unsigned edges;
|
uint32_t edges;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Edge {
|
struct Edge {
|
||||||
|
87
DataStructures/HilbertValue.h
Normal file
87
DataStructures/HilbertValue.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HILBERTVALUE_H_
|
||||||
|
#define HILBERTVALUE_H_
|
||||||
|
|
||||||
|
#include <boost/integer.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
// computes a 64 bit value that corresponds to the hilbert space filling curve
|
||||||
|
|
||||||
|
class HilbertCode : boost::noncopyable {
|
||||||
|
public:
|
||||||
|
static uint64_t GetHilbertNumberForCoordinate(
|
||||||
|
const _Coordinate & current_coordinate) {
|
||||||
|
unsigned location[2];
|
||||||
|
location[0] = current_coordinate.lat+( 90*100000);
|
||||||
|
location[1] = current_coordinate.lon+(180*100000);
|
||||||
|
|
||||||
|
TransposeCoordinate(location);
|
||||||
|
const uint64_t result = BitInterleaving(location[0], location[1]);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static inline uint64_t BitInterleaving(const uint32_t a, const uint32_t b) {
|
||||||
|
uint64_t result = 0;
|
||||||
|
for(int8_t index = 31; index >= 0; --index){
|
||||||
|
result |= (a >> index) & 1;
|
||||||
|
result <<= 1;
|
||||||
|
result |= (b >> index) & 1;
|
||||||
|
if(0 != index){
|
||||||
|
result <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void TransposeCoordinate( uint32_t * X) {
|
||||||
|
uint32_t M = 1 << (32-1), P, Q, t;
|
||||||
|
int i;
|
||||||
|
// Inverse undo
|
||||||
|
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||||
|
P=Q-1;
|
||||||
|
for( i = 0; i < 2; ++i ) {
|
||||||
|
if( X[i] & Q ) {
|
||||||
|
X[0] ^= P; // invert
|
||||||
|
} else {
|
||||||
|
t = (X[0]^X[i]) & P;
|
||||||
|
X[0] ^= t;
|
||||||
|
X[i] ^= t;
|
||||||
|
}
|
||||||
|
} // exchange
|
||||||
|
}
|
||||||
|
// Gray encode
|
||||||
|
for( i = 1; i < 2; ++i ) {
|
||||||
|
X[i] ^= X[i-1];
|
||||||
|
}
|
||||||
|
t=0;
|
||||||
|
for( Q = M; Q > 1; Q >>= 1 ) {
|
||||||
|
if( X[2-1] & Q ) {
|
||||||
|
t ^= Q-1;
|
||||||
|
}
|
||||||
|
} //check if this for loop is wrong
|
||||||
|
for( i = 0; i < 2; ++i ) {
|
||||||
|
X[i] ^= t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* HILBERTVALUE_H_ */
|
@ -21,34 +21,49 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef NODEINFORMATIONHELPDESK_H_
|
#ifndef NODEINFORMATIONHELPDESK_H_
|
||||||
#define NODEINFORMATIONHELPDESK_H_
|
#define NODEINFORMATIONHELPDESK_H_
|
||||||
|
|
||||||
|
#include "NodeCoords.h"
|
||||||
|
#include "PhantomNodes.h"
|
||||||
|
#include "QueryEdge.h"
|
||||||
|
#include "StaticRTree.h"
|
||||||
|
#include "../Contractor/EdgeBasedGraphFactory.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
typedef EdgeBasedGraphFactory::EdgeBasedNode RTreeLeaf;
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "NNGrid.h"
|
|
||||||
#include "PhantomNodes.h"
|
|
||||||
#include "NodeCoords.h"
|
|
||||||
|
|
||||||
class NodeInformationHelpDesk : boost::noncopyable{
|
class NodeInformationHelpDesk : boost::noncopyable{
|
||||||
public:
|
public:
|
||||||
NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc) : numberOfNodes(_numberOfNodes), checkSum(crc) {
|
NodeInformationHelpDesk(
|
||||||
readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
|
const char* ramIndexInput,
|
||||||
assert(0 == coordinateVector.size());
|
const char* fileIndexInput,
|
||||||
|
const unsigned number_of_nodes,
|
||||||
|
const unsigned crc) : number_of_nodes(number_of_nodes), checkSum(crc) {
|
||||||
|
read_only_rtree = new StaticRTree<RTreeLeaf>(
|
||||||
|
ramIndexInput,
|
||||||
|
fileIndexInput
|
||||||
|
);
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
0 == coordinateVector.size(),
|
||||||
|
"Coordinate vector not empty"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Todo: Shared memory mechanism
|
//Todo: Shared memory mechanism
|
||||||
// NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned crc) : checkSum(crc) {
|
|
||||||
// readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput);
|
|
||||||
// }
|
|
||||||
|
|
||||||
~NodeInformationHelpDesk() {
|
~NodeInformationHelpDesk() {
|
||||||
delete readOnlyGrid;
|
delete read_only_rtree;
|
||||||
}
|
}
|
||||||
void initNNGrid(std::ifstream& nodesInstream, std::ifstream& edgesInStream) {
|
|
||||||
|
void initNNGrid(
|
||||||
|
std::ifstream& nodesInstream,
|
||||||
|
std::ifstream& edgesInStream
|
||||||
|
) {
|
||||||
DEBUG("Loading node data");
|
DEBUG("Loading node data");
|
||||||
NodeInfo b;
|
NodeInfo b;
|
||||||
while(!nodesInstream.eof()) {
|
while(!nodesInstream.eof()) {
|
||||||
@ -68,20 +83,15 @@ public:
|
|||||||
OriginalEdgeData deserialized_originalEdgeData;
|
OriginalEdgeData deserialized_originalEdgeData;
|
||||||
for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
|
for(unsigned i = 0; i < numberOfOrigEdges; ++i) {
|
||||||
edgesInStream.read((char*)&(deserialized_originalEdgeData), sizeof(OriginalEdgeData));
|
edgesInStream.read((char*)&(deserialized_originalEdgeData), sizeof(OriginalEdgeData));
|
||||||
origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
|
origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode;
|
||||||
origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID;
|
origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID;
|
||||||
origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
|
origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction;
|
||||||
}
|
}
|
||||||
edgesInStream.close();
|
edgesInStream.close();
|
||||||
DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
|
DEBUG("Loaded " << numberOfOrigEdges << " orig edges");
|
||||||
DEBUG("Opening NN indices");
|
DEBUG("Opening NN indices");
|
||||||
readOnlyGrid->OpenIndexFiles();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// void initNNGrid() {
|
|
||||||
// readOnlyGrid->OpenIndexFiles();
|
|
||||||
// }
|
|
||||||
|
|
||||||
inline int getLatitudeOfNode(const unsigned id) const {
|
inline int getLatitudeOfNode(const unsigned id) const {
|
||||||
const NodeID node = origEdgeData_viaNode.at(id);
|
const NodeID node = origEdgeData_viaNode.at(id);
|
||||||
return coordinateVector.at(node).lat;
|
return coordinateVector.at(node).lat;
|
||||||
@ -100,24 +110,36 @@ public:
|
|||||||
return origEdgeData_turnInstruction.at(id);
|
return origEdgeData_turnInstruction.at(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NodeID getNumberOfNodes() const { return numberOfNodes; }
|
inline NodeID getNumberOfNodes() const {
|
||||||
inline NodeID getNumberOfNodes2() const { return coordinateVector.size(); }
|
return number_of_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool FindNearestNodeCoordForLatLon(const _Coordinate& coord, _Coordinate& result) const {
|
inline NodeID getNumberOfNodes2() const {
|
||||||
return readOnlyGrid->FindNearestCoordinateOnEdgeInNodeBasedGraph(coord, result);
|
return coordinateVector.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) {
|
inline bool FindNearestNodeCoordForLatLon(
|
||||||
return readOnlyGrid->FindPhantomNodeForCoordinate(location, resultNode, zoomLevel);
|
const _Coordinate& input_coordinate,
|
||||||
}
|
_Coordinate& result,
|
||||||
|
const unsigned zoom_level = 18
|
||||||
|
) const {
|
||||||
|
PhantomNode resulting_phantom_node;
|
||||||
|
bool foundNode = FindPhantomNodeForCoordinate(input_coordinate, resulting_phantom_node, zoom_level);
|
||||||
|
result = resulting_phantom_node.location;
|
||||||
|
return foundNode;
|
||||||
|
}
|
||||||
|
|
||||||
inline void FindRoutingStarts(const _Coordinate &start, const _Coordinate &target, PhantomNodes & phantomNodes, const unsigned zoomLevel) const {
|
inline bool FindPhantomNodeForCoordinate(
|
||||||
readOnlyGrid->FindRoutingStarts(start, target, phantomNodes, zoomLevel);
|
const _Coordinate & input_coordinate,
|
||||||
}
|
PhantomNode & resulting_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
inline void FindNearestPointOnEdge(const _Coordinate & input, _Coordinate& output){
|
) const {
|
||||||
readOnlyGrid->FindNearestPointOnEdge(input, output);
|
return read_only_rtree->FindPhantomNodeForCoordinate(
|
||||||
}
|
input_coordinate,
|
||||||
|
resulting_phantom_node,
|
||||||
|
zoom_level
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned GetCheckSum() const {
|
inline unsigned GetCheckSum() const {
|
||||||
return checkSum;
|
return checkSum;
|
||||||
@ -129,8 +151,8 @@ private:
|
|||||||
std::vector<unsigned> origEdgeData_nameID;
|
std::vector<unsigned> origEdgeData_nameID;
|
||||||
std::vector<TurnInstruction> origEdgeData_turnInstruction;
|
std::vector<TurnInstruction> origEdgeData_turnInstruction;
|
||||||
|
|
||||||
ReadOnlyGrid * readOnlyGrid;
|
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * read_only_rtree;
|
||||||
const unsigned numberOfNodes;
|
const unsigned number_of_nodes;
|
||||||
const unsigned checkSum;
|
const unsigned checkSum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
89
DataStructures/SearchEngine.cpp
Normal file
89
DataStructures/SearchEngine.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SearchEngine.h"
|
||||||
|
|
||||||
|
SearchEngine::SearchEngine(
|
||||||
|
QueryGraph * g,
|
||||||
|
NodeInformationHelpDesk * nh,
|
||||||
|
std::vector<std::string> & n
|
||||||
|
) :
|
||||||
|
_queryData(g, nh, n),
|
||||||
|
shortestPath(_queryData),
|
||||||
|
alternativePaths(_queryData)
|
||||||
|
{}
|
||||||
|
SearchEngine::~SearchEngine() {}
|
||||||
|
|
||||||
|
void SearchEngine::GetCoordinatesForNodeID(
|
||||||
|
NodeID id,
|
||||||
|
_Coordinate& result
|
||||||
|
) const {
|
||||||
|
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
|
||||||
|
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngine::FindPhantomNodeForCoordinate(
|
||||||
|
const _Coordinate & location,
|
||||||
|
PhantomNode & result,
|
||||||
|
const unsigned zoomLevel
|
||||||
|
) const {
|
||||||
|
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(
|
||||||
|
location,
|
||||||
|
result, zoomLevel
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeID SearchEngine::GetNameIDForOriginDestinationNodeID(
|
||||||
|
const NodeID s,
|
||||||
|
const NodeID t
|
||||||
|
) const {
|
||||||
|
if(s == t){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EdgeID e = _queryData.graph->FindEdge(s, t);
|
||||||
|
if(e == UINT_MAX) {
|
||||||
|
e = _queryData.graph->FindEdge( t, s );
|
||||||
|
}
|
||||||
|
if(UINT_MAX == e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(e != UINT_MAX);
|
||||||
|
const QueryEdge::EdgeData ed = _queryData.graph->GetEdgeData(e);
|
||||||
|
return ed.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SearchEngine::GetEscapedNameForNameID(const unsigned nameID) const {
|
||||||
|
bool is_name_invalid = (nameID >= _queryData.names.size() || nameID == 0);
|
||||||
|
if (is_name_invalid) {
|
||||||
|
return std::string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTMLEntitize(_queryData.names.at(nameID));
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchEngineHeapPtr SearchEngineData::forwardHeap;
|
||||||
|
SearchEngineHeapPtr SearchEngineData::backwardHeap;
|
||||||
|
|
||||||
|
SearchEngineHeapPtr SearchEngineData::forwardHeap2;
|
||||||
|
SearchEngineHeapPtr SearchEngineData::backwardHeap2;
|
||||||
|
|
||||||
|
SearchEngineHeapPtr SearchEngineData::forwardHeap3;
|
||||||
|
SearchEngineHeapPtr SearchEngineData::backwardHeap3;
|
||||||
|
|
@ -21,152 +21,48 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef SEARCHENGINE_H_
|
#ifndef SEARCHENGINE_H_
|
||||||
#define SEARCHENGINE_H_
|
#define SEARCHENGINE_H_
|
||||||
|
|
||||||
#include <climits>
|
#include "Coordinate.h"
|
||||||
#include <deque>
|
|
||||||
#include "SimpleStack.h"
|
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#include "BinaryHeap.h"
|
|
||||||
#include "NodeInformationHelpDesk.h"
|
#include "NodeInformationHelpDesk.h"
|
||||||
#include "PhantomNodes.h"
|
#include "PhantomNodes.h"
|
||||||
|
#include "QueryEdge.h"
|
||||||
|
#include "SearchEngineData.h"
|
||||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||||
#include "../RoutingAlgorithms/BasicRoutingInterface.h"
|
|
||||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct _HeapData {
|
#include <climits>
|
||||||
NodeID parent;
|
#include <string>
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
#include <vector>
|
||||||
};
|
|
||||||
|
|
||||||
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
|
|
||||||
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT>
|
|
||||||
struct SearchEngineData {
|
|
||||||
typedef GraphT Graph;
|
|
||||||
typedef QueryHeapType QueryHeap;
|
|
||||||
SearchEngineData(GraphT * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
|
|
||||||
const GraphT * graph;
|
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
|
||||||
std::vector<std::string> & names;
|
|
||||||
static SearchEngineHeapPtr forwardHeap;
|
|
||||||
static SearchEngineHeapPtr backwardHeap;
|
|
||||||
static SearchEngineHeapPtr forwardHeap2;
|
|
||||||
static SearchEngineHeapPtr backwardHeap2;
|
|
||||||
static SearchEngineHeapPtr forwardHeap3;
|
|
||||||
static SearchEngineHeapPtr backwardHeap3;
|
|
||||||
|
|
||||||
inline void InitializeOrClearFirstThreadLocalStorage() {
|
|
||||||
if(!forwardHeap.get()) {
|
|
||||||
forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
forwardHeap->Clear();
|
|
||||||
|
|
||||||
if(!backwardHeap.get()) {
|
|
||||||
backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backwardHeap->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InitializeOrClearSecondThreadLocalStorage() {
|
|
||||||
if(!forwardHeap2.get()) {
|
|
||||||
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
forwardHeap2->Clear();
|
|
||||||
|
|
||||||
if(!backwardHeap2.get()) {
|
|
||||||
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backwardHeap2->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InitializeOrClearThirdThreadLocalStorage() {
|
|
||||||
if(!forwardHeap3.get()) {
|
|
||||||
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
forwardHeap3->Clear();
|
|
||||||
|
|
||||||
if(!backwardHeap3.get()) {
|
|
||||||
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
backwardHeap3->Clear();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT>
|
|
||||||
class SearchEngine {
|
class SearchEngine {
|
||||||
private:
|
private:
|
||||||
typedef SearchEngineData<EdgeData, GraphT> SearchEngineDataT;
|
SearchEngineData _queryData;
|
||||||
SearchEngineDataT _queryData;
|
|
||||||
|
|
||||||
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
|
|
||||||
public:
|
public:
|
||||||
ShortestPathRouting<SearchEngineDataT> shortestPath;
|
ShortestPathRouting<SearchEngineData> shortestPath;
|
||||||
AlternativeRouting<SearchEngineDataT> alternativePaths;
|
AlternativeRouting<SearchEngineData> alternativePaths;
|
||||||
|
|
||||||
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :
|
SearchEngine(
|
||||||
_queryData(g, nh, n),
|
QueryGraph * g,
|
||||||
shortestPath(_queryData),
|
NodeInformationHelpDesk * nh,
|
||||||
alternativePaths(_queryData)
|
std::vector<std::string> & n
|
||||||
{}
|
);
|
||||||
~SearchEngine() {}
|
~SearchEngine();
|
||||||
|
|
||||||
inline void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
|
void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const;
|
||||||
result.lat = _queryData.nodeHelpDesk->getLatitudeOfNode(id);
|
|
||||||
result.lon = _queryData.nodeHelpDesk->getLongitudeOfNode(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) const {
|
void FindPhantomNodeForCoordinate(
|
||||||
_queryData.nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
|
const _Coordinate & location,
|
||||||
}
|
PhantomNode & result,
|
||||||
|
unsigned zoomLevel
|
||||||
|
) const;
|
||||||
|
|
||||||
inline void FindPhantomNodeForCoordinate(const _Coordinate & location, PhantomNode & result, unsigned zoomLevel) const {
|
NodeID GetNameIDForOriginDestinationNodeID(
|
||||||
_queryData.nodeHelpDesk->FindPhantomNodeForCoordinate(location, result, zoomLevel);
|
const NodeID s, const NodeID t) const;
|
||||||
}
|
|
||||||
|
|
||||||
inline NodeID GetNameIDForOriginDestinationNodeID(const NodeID s, const NodeID t) const {
|
|
||||||
if(s == t)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
EdgeID e = _queryData.graph->FindEdge(s, t);
|
|
||||||
if(e == UINT_MAX)
|
|
||||||
e = _queryData.graph->FindEdge( t, s );
|
|
||||||
if(UINT_MAX == e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
assert(e != UINT_MAX);
|
|
||||||
const EdgeData ed = _queryData.graph->GetEdgeData(e);
|
|
||||||
return ed.via;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string GetEscapedNameForNameID(const unsigned nameID) const {
|
|
||||||
return ((nameID >= _queryData.names.size() || nameID == 0) ? std::string("") : HTMLEntitize(_queryData.names.at(nameID)));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const {
|
|
||||||
const unsigned nameID = _queryData.graph->GetEdgeData(edgeID).nameID1;
|
|
||||||
return GetEscapedNameForNameID(nameID);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string GetEscapedNameForNameID(const unsigned nameID) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap;
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap;
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap2;
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap2;
|
|
||||||
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::forwardHeap3;
|
|
||||||
template<class EdgeData, class GraphT> SearchEngineHeapPtr SearchEngineData<EdgeData, GraphT>::backwardHeap3;
|
|
||||||
|
|
||||||
#endif /* SEARCHENGINE_H_ */
|
#endif /* SEARCHENGINE_H_ */
|
||||||
|
60
DataStructures/SearchEngineData.cpp
Normal file
60
DataStructures/SearchEngineData.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SearchEngineData.h"
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearFirstThreadLocalStorage() {
|
||||||
|
if(!forwardHeap.get()) {
|
||||||
|
forwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
forwardHeap->Clear();
|
||||||
|
}
|
||||||
|
if(!backwardHeap.get()) {
|
||||||
|
backwardHeap.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
backwardHeap->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearSecondThreadLocalStorage() {
|
||||||
|
if(!forwardHeap2.get()) {
|
||||||
|
forwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
forwardHeap2->Clear();
|
||||||
|
}
|
||||||
|
if(!backwardHeap2.get()) {
|
||||||
|
backwardHeap2.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
backwardHeap2->Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchEngineData::InitializeOrClearThirdThreadLocalStorage() {
|
||||||
|
if(!forwardHeap3.get()) {
|
||||||
|
forwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
forwardHeap3->Clear();
|
||||||
|
}
|
||||||
|
if(!backwardHeap3.get()) {
|
||||||
|
backwardHeap3.reset(new QueryHeap(nodeHelpDesk->getNumberOfNodes()));
|
||||||
|
} else {
|
||||||
|
backwardHeap3->Clear();
|
||||||
|
}
|
||||||
|
}
|
60
DataStructures/SearchEngineData.h
Normal file
60
DataStructures/SearchEngineData.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BinaryHeap.h"
|
||||||
|
#include "QueryEdge.h"
|
||||||
|
#include "NodeInformationHelpDesk.h"
|
||||||
|
#include "StaticGraph.h"
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct _HeapData {
|
||||||
|
NodeID parent;
|
||||||
|
_HeapData( NodeID p ) : parent(p) { }
|
||||||
|
};
|
||||||
|
typedef StaticGraph<QueryEdge::EdgeData> QueryGraph;
|
||||||
|
typedef BinaryHeap< NodeID, NodeID, int, _HeapData, UnorderedMapStorage<NodeID, int> > QueryHeapType;
|
||||||
|
typedef boost::thread_specific_ptr<QueryHeapType> SearchEngineHeapPtr;
|
||||||
|
|
||||||
|
struct SearchEngineData {
|
||||||
|
typedef QueryGraph Graph;
|
||||||
|
typedef QueryHeapType QueryHeap;
|
||||||
|
SearchEngineData(QueryGraph * g, NodeInformationHelpDesk * nh, std::vector<std::string> & n) :graph(g), nodeHelpDesk(nh), names(n) {}
|
||||||
|
const QueryGraph * graph;
|
||||||
|
NodeInformationHelpDesk * nodeHelpDesk;
|
||||||
|
std::vector<std::string> & names;
|
||||||
|
static SearchEngineHeapPtr forwardHeap;
|
||||||
|
static SearchEngineHeapPtr backwardHeap;
|
||||||
|
static SearchEngineHeapPtr forwardHeap2;
|
||||||
|
static SearchEngineHeapPtr backwardHeap2;
|
||||||
|
static SearchEngineHeapPtr forwardHeap3;
|
||||||
|
static SearchEngineHeapPtr backwardHeap3;
|
||||||
|
|
||||||
|
void InitializeOrClearFirstThreadLocalStorage();
|
||||||
|
|
||||||
|
void InitializeOrClearSecondThreadLocalStorage();
|
||||||
|
|
||||||
|
void InitializeOrClearThirdThreadLocalStorage();
|
||||||
|
};
|
909
DataStructures/StaticRTree.h
Normal file
909
DataStructures/StaticRTree.h
Normal file
@ -0,0 +1,909 @@
|
|||||||
|
/*
|
||||||
|
open source routing machine
|
||||||
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STATICRTREE_H_
|
||||||
|
#define STATICRTREE_H_
|
||||||
|
|
||||||
|
#include "MercatorUtil.h"
|
||||||
|
#include "TimingUtil.h"
|
||||||
|
#include "Coordinate.h"
|
||||||
|
#include "PhantomNodes.h"
|
||||||
|
#include "DeallocatingVector.h"
|
||||||
|
#include "HilbertValue.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/algorithm/minmax.hpp>
|
||||||
|
#include <boost/algorithm/minmax_element.hpp>
|
||||||
|
#include <boost/range/algorithm_ext/erase.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cfloat>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <queue>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
//tuning parameters
|
||||||
|
const static uint32_t RTREE_BRANCHING_FACTOR = 50;
|
||||||
|
const static uint32_t RTREE_LEAF_NODE_SIZE = 1170;
|
||||||
|
|
||||||
|
// Implements a static, i.e. packed, R-tree
|
||||||
|
|
||||||
|
static boost::thread_specific_ptr<std::ifstream> thread_local_rtree_stream;
|
||||||
|
|
||||||
|
template<class DataT>
|
||||||
|
class StaticRTree : boost::noncopyable {
|
||||||
|
private:
|
||||||
|
struct RectangleInt2D {
|
||||||
|
RectangleInt2D() :
|
||||||
|
min_lon(INT_MAX),
|
||||||
|
max_lon(INT_MIN),
|
||||||
|
min_lat(INT_MAX),
|
||||||
|
max_lat(INT_MIN) {}
|
||||||
|
|
||||||
|
int32_t min_lon, max_lon;
|
||||||
|
int32_t min_lat, max_lat;
|
||||||
|
|
||||||
|
inline void InitializeMBRectangle(
|
||||||
|
const DataT * objects,
|
||||||
|
const uint32_t element_count
|
||||||
|
) {
|
||||||
|
for(uint32_t i = 0; i < element_count; ++i) {
|
||||||
|
min_lon = std::min(
|
||||||
|
min_lon, std::min(objects[i].lon1, objects[i].lon2)
|
||||||
|
);
|
||||||
|
max_lon = std::max(
|
||||||
|
max_lon, std::max(objects[i].lon1, objects[i].lon2)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_lat = std::min(
|
||||||
|
min_lat, std::min(objects[i].lat1, objects[i].lat2)
|
||||||
|
);
|
||||||
|
max_lat = std::max(
|
||||||
|
max_lat, std::max(objects[i].lat1, objects[i].lat2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void AugmentMBRectangle(const RectangleInt2D & other) {
|
||||||
|
min_lon = std::min(min_lon, other.min_lon);
|
||||||
|
max_lon = std::max(max_lon, other.max_lon);
|
||||||
|
min_lat = std::min(min_lat, other.min_lat);
|
||||||
|
max_lat = std::max(max_lat, other.max_lat);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline _Coordinate Centroid() const {
|
||||||
|
_Coordinate centroid;
|
||||||
|
//The coordinates of the midpoints are given by:
|
||||||
|
//x = (x1 + x2) /2 and y = (y1 + y2) /2.
|
||||||
|
centroid.lon = (min_lon + max_lon)/2;
|
||||||
|
centroid.lat = (min_lat + max_lat)/2;
|
||||||
|
return centroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Intersects(const RectangleInt2D & other) const {
|
||||||
|
_Coordinate upper_left (other.max_lat, other.min_lon);
|
||||||
|
_Coordinate upper_right(other.max_lat, other.max_lon);
|
||||||
|
_Coordinate lower_right(other.min_lat, other.max_lon);
|
||||||
|
_Coordinate lower_left (other.min_lat, other.min_lon);
|
||||||
|
|
||||||
|
return (
|
||||||
|
Contains(upper_left)
|
||||||
|
|| Contains(upper_right)
|
||||||
|
|| Contains(lower_right)
|
||||||
|
|| Contains(lower_left)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetMinDist(const _Coordinate & location) const {
|
||||||
|
bool is_contained = Contains(location);
|
||||||
|
if (is_contained) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
max_lat,
|
||||||
|
min_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
max_lat,
|
||||||
|
max_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
min_lat,
|
||||||
|
max_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
min_dist = std::min(
|
||||||
|
min_dist,
|
||||||
|
ApproximateDistance(
|
||||||
|
location.lat,
|
||||||
|
location.lon,
|
||||||
|
min_lat,
|
||||||
|
min_lon
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return min_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetMinMaxDist(const _Coordinate & location) const {
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
//Get minmax distance to each of the four sides
|
||||||
|
_Coordinate upper_left (max_lat, min_lon);
|
||||||
|
_Coordinate upper_right(max_lat, max_lon);
|
||||||
|
_Coordinate lower_right(min_lat, max_lon);
|
||||||
|
_Coordinate lower_left (min_lat, min_lon);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, upper_left ),
|
||||||
|
ApproximateDistance(location, upper_right)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, upper_right),
|
||||||
|
ApproximateDistance(location, lower_right)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, lower_right),
|
||||||
|
ApproximateDistance(location, lower_left )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
min_max_dist = std::min(
|
||||||
|
min_max_dist,
|
||||||
|
std::max(
|
||||||
|
ApproximateDistance(location, lower_left ),
|
||||||
|
ApproximateDistance(location, upper_left )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return min_max_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool Contains(const _Coordinate & location) const {
|
||||||
|
bool lats_contained =
|
||||||
|
(location.lat > min_lat) && (location.lat < max_lat);
|
||||||
|
bool lons_contained =
|
||||||
|
(location.lon > min_lon) && (location.lon < max_lon);
|
||||||
|
return lats_contained && lons_contained;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline friend std::ostream & operator<< ( std::ostream & out, const RectangleInt2D & rect ) {
|
||||||
|
out << rect.min_lat/100000. << "," << rect.min_lon/100000. << " " << rect.max_lat/100000. << "," << rect.max_lon/100000.;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef RectangleInt2D RectangleT;
|
||||||
|
|
||||||
|
struct WrappedInputElement {
|
||||||
|
explicit WrappedInputElement(const uint32_t _array_index, const uint64_t _hilbert_value) :
|
||||||
|
m_array_index(_array_index), m_hilbert_value(_hilbert_value) {}
|
||||||
|
WrappedInputElement() : m_array_index(UINT_MAX), m_hilbert_value(0) {}
|
||||||
|
|
||||||
|
uint32_t m_array_index;
|
||||||
|
uint64_t m_hilbert_value;
|
||||||
|
|
||||||
|
inline bool operator<(const WrappedInputElement & other) const {
|
||||||
|
return m_hilbert_value < other.m_hilbert_value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LeafNode {
|
||||||
|
LeafNode() : object_count(0) {}
|
||||||
|
uint32_t object_count;
|
||||||
|
DataT objects[RTREE_LEAF_NODE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TreeNode {
|
||||||
|
TreeNode() : child_count(0), child_is_on_disk(false) {}
|
||||||
|
RectangleT minimum_bounding_rectangle;
|
||||||
|
uint32_t child_count:31;
|
||||||
|
bool child_is_on_disk:1;
|
||||||
|
uint32_t children[RTREE_BRANCHING_FACTOR];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueryCandidate {
|
||||||
|
explicit QueryCandidate(const uint32_t n_id, const double dist) : node_id(n_id), min_dist(dist)/*, minmax_dist(DBL_MAX)*/ {}
|
||||||
|
QueryCandidate() : node_id(UINT_MAX), min_dist(DBL_MAX)/*, minmax_dist(DBL_MAX)*/ {}
|
||||||
|
uint32_t node_id;
|
||||||
|
double min_dist;
|
||||||
|
// double minmax_dist;
|
||||||
|
inline bool operator<(const QueryCandidate & other) const {
|
||||||
|
return min_dist < other.min_dist;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<TreeNode> m_search_tree;
|
||||||
|
uint64_t m_element_count;
|
||||||
|
|
||||||
|
std::string m_leaf_node_filename;
|
||||||
|
public:
|
||||||
|
//Construct a pack R-Tree from the input-list with Kamel-Faloutsos algorithm [1]
|
||||||
|
explicit StaticRTree(std::vector<DataT> & input_data_vector, const char * tree_node_filename, const char * leaf_node_filename) :
|
||||||
|
m_leaf_node_filename(leaf_node_filename) {
|
||||||
|
m_element_count = input_data_vector.size();
|
||||||
|
//remove elements that are flagged to be ignored
|
||||||
|
// boost::remove_erase_if(input_data_vector, boost::bind(&DataT::isIgnored, _1 ));
|
||||||
|
|
||||||
|
INFO("constructing r-tree of " << m_element_count << " elements");
|
||||||
|
// INFO("sizeof(LeafNode)=" << sizeof(LeafNode));
|
||||||
|
// INFO("sizeof(TreeNode)=" << sizeof(TreeNode));
|
||||||
|
// INFO("sizeof(WrappedInputElement)=" << sizeof(WrappedInputElement));
|
||||||
|
double time1 = get_timestamp();
|
||||||
|
std::vector<WrappedInputElement> input_wrapper_vector(input_data_vector.size());
|
||||||
|
|
||||||
|
//generate auxiliary vector of hilbert-values
|
||||||
|
#pragma omp parallel for schedule(guided)
|
||||||
|
for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) {
|
||||||
|
//INFO("ID: " << input_data_vector[element_counter].id);
|
||||||
|
input_wrapper_vector[element_counter].m_array_index = element_counter;
|
||||||
|
//Get Hilbert-Value for centroid in mercartor projection
|
||||||
|
DataT & current_element = input_data_vector[element_counter];
|
||||||
|
_Coordinate current_centroid = current_element.Centroid();
|
||||||
|
current_centroid.lat = 100000*lat2y(current_centroid.lat/100000.);
|
||||||
|
|
||||||
|
uint64_t current_hilbert_value = HilbertCode::GetHilbertNumberForCoordinate(current_centroid);
|
||||||
|
input_wrapper_vector[element_counter].m_hilbert_value = current_hilbert_value;
|
||||||
|
|
||||||
|
}
|
||||||
|
//INFO("finished wrapper setup");
|
||||||
|
|
||||||
|
//open leaf file
|
||||||
|
std::ofstream leaf_node_file(leaf_node_filename, std::ios::binary);
|
||||||
|
leaf_node_file.write((char*) &m_element_count, sizeof(uint64_t));
|
||||||
|
|
||||||
|
//sort the hilbert-value representatives
|
||||||
|
std::sort(input_wrapper_vector.begin(), input_wrapper_vector.end());
|
||||||
|
// INFO("finished sorting");
|
||||||
|
std::vector<TreeNode> tree_nodes_in_level;
|
||||||
|
|
||||||
|
//pack M elements into leaf node and write to leaf file
|
||||||
|
uint64_t processed_objects_count = 0;
|
||||||
|
while(processed_objects_count < m_element_count) {
|
||||||
|
|
||||||
|
LeafNode current_leaf;
|
||||||
|
TreeNode current_node;
|
||||||
|
for(uint32_t current_element_index = 0; RTREE_LEAF_NODE_SIZE > current_element_index; ++current_element_index) {
|
||||||
|
if(m_element_count > (processed_objects_count + current_element_index)) {
|
||||||
|
// INFO("Checking element " << (processed_objects_count + current_element_index));
|
||||||
|
uint32_t index_of_next_object = input_wrapper_vector[processed_objects_count + current_element_index].m_array_index;
|
||||||
|
current_leaf.objects[current_element_index] = input_data_vector[index_of_next_object];
|
||||||
|
++current_leaf.object_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(0 == processed_objects_count) {
|
||||||
|
for(uint32_t i = 0; i < current_leaf.object_count; ++i) {
|
||||||
|
//INFO("[" << i << "] id: " << current_leaf.objects[i].id << ", weight: " << current_leaf.objects[i].weight << ", " << current_leaf.objects[i].lat1/100000. << "," << current_leaf.objects[i].lon1/100000. << ";" << current_leaf.objects[i].lat2/100000. << "," << current_leaf.objects[i].lon2/100000.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//generate tree node that resemble the objects in leaf and store it for next level
|
||||||
|
current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count);
|
||||||
|
current_node.child_is_on_disk = true;
|
||||||
|
current_node.children[0] = tree_nodes_in_level.size();
|
||||||
|
tree_nodes_in_level.push_back(current_node);
|
||||||
|
|
||||||
|
//write leaf_node to leaf node file
|
||||||
|
leaf_node_file.write((char*)¤t_leaf, sizeof(current_leaf));
|
||||||
|
processed_objects_count += current_leaf.object_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO("wrote " << processed_objects_count << " leaf objects");
|
||||||
|
|
||||||
|
//close leaf file
|
||||||
|
leaf_node_file.close();
|
||||||
|
|
||||||
|
uint32_t processing_level = 0;
|
||||||
|
while(1 < tree_nodes_in_level.size()) {
|
||||||
|
// INFO("processing " << (uint32_t)tree_nodes_in_level.size() << " tree nodes in level " << processing_level);
|
||||||
|
std::vector<TreeNode> tree_nodes_in_next_level;
|
||||||
|
uint32_t processed_tree_nodes_in_level = 0;
|
||||||
|
while(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
||||||
|
TreeNode parent_node;
|
||||||
|
//pack RTREE_BRANCHING_FACTOR elements into tree_nodes each
|
||||||
|
for(uint32_t current_child_node_index = 0; RTREE_BRANCHING_FACTOR > current_child_node_index; ++current_child_node_index) {
|
||||||
|
if(processed_tree_nodes_in_level < tree_nodes_in_level.size()) {
|
||||||
|
TreeNode & current_child_node = tree_nodes_in_level[processed_tree_nodes_in_level];
|
||||||
|
//add tree node to parent entry
|
||||||
|
parent_node.children[current_child_node_index] = m_search_tree.size();
|
||||||
|
m_search_tree.push_back(current_child_node);
|
||||||
|
//augment MBR of parent
|
||||||
|
parent_node.minimum_bounding_rectangle.AugmentMBRectangle(current_child_node.minimum_bounding_rectangle);
|
||||||
|
//increase counters
|
||||||
|
++parent_node.child_count;
|
||||||
|
++processed_tree_nodes_in_level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree_nodes_in_next_level.push_back(parent_node);
|
||||||
|
// INFO("processed: " << processed_tree_nodes_in_level << ", generating " << (uint32_t)tree_nodes_in_next_level.size() << " parents");
|
||||||
|
}
|
||||||
|
tree_nodes_in_level.swap(tree_nodes_in_next_level);
|
||||||
|
++processing_level;
|
||||||
|
}
|
||||||
|
BOOST_ASSERT_MSG(1 == tree_nodes_in_level.size(), "tree broken, more than one root node");
|
||||||
|
//last remaining entry is the root node;
|
||||||
|
// INFO("root node has " << (uint32_t)tree_nodes_in_level[0].child_count << " children");
|
||||||
|
//store root node
|
||||||
|
m_search_tree.push_back(tree_nodes_in_level[0]);
|
||||||
|
|
||||||
|
//reverse and renumber tree to have root at index 0
|
||||||
|
std::reverse(m_search_tree.begin(), m_search_tree.end());
|
||||||
|
#pragma omp parallel for schedule(guided)
|
||||||
|
for(uint32_t i = 0; i < m_search_tree.size(); ++i) {
|
||||||
|
TreeNode & current_tree_node = m_search_tree[i];
|
||||||
|
for(uint32_t j = 0; j < current_tree_node.child_count; ++j) {
|
||||||
|
const uint32_t old_id = current_tree_node.children[j];
|
||||||
|
const uint32_t new_id = m_search_tree.size() - old_id - 1;
|
||||||
|
current_tree_node.children[j] = new_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//open tree file
|
||||||
|
std::ofstream tree_node_file(tree_node_filename, std::ios::binary);
|
||||||
|
uint32_t size_of_tree = m_search_tree.size();
|
||||||
|
BOOST_ASSERT_MSG(0 < size_of_tree, "tree empty");
|
||||||
|
tree_node_file.write((char *)&size_of_tree, sizeof(uint32_t));
|
||||||
|
tree_node_file.write((char *)&m_search_tree[0], sizeof(TreeNode)*size_of_tree);
|
||||||
|
//close tree node file.
|
||||||
|
tree_node_file.close();
|
||||||
|
double time2 = get_timestamp();
|
||||||
|
// INFO("written " << processed_objects_count << " leafs in " << sizeof(LeafNode)*(1+(unsigned)std::ceil(processed_objects_count/RTREE_LEAF_NODE_SIZE) )+sizeof(uint64_t) << " bytes");
|
||||||
|
// INFO("written search tree of " << size_of_tree << " tree nodes in " << sizeof(TreeNode)*size_of_tree+sizeof(uint32_t) << " bytes");
|
||||||
|
INFO("finished r-tree construction in " << (time2-time1) << " seconds");
|
||||||
|
|
||||||
|
//todo: test queries
|
||||||
|
/* INFO("first MBR:" << m_search_tree[0].minimum_bounding_rectangle);
|
||||||
|
|
||||||
|
DataT result;
|
||||||
|
time1 = get_timestamp();
|
||||||
|
bool found_nearest = NearestNeighbor(_Coordinate(50.191085,8.466479), result);
|
||||||
|
time2 = get_timestamp();
|
||||||
|
INFO("found nearest element to (50.191085,8.466479): " << (found_nearest ? "yes" : "no") << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
|
||||||
|
time1 = get_timestamp();
|
||||||
|
found_nearest = NearestNeighbor(_Coordinate(50.23979, 8.51882), result);
|
||||||
|
time2 = get_timestamp();
|
||||||
|
INFO("found nearest element to (50.23979, 8.51882): " << (found_nearest ? "yes" : "no") << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
|
||||||
|
time1 = get_timestamp();
|
||||||
|
found_nearest = NearestNeighbor(_Coordinate(49.0316,2.6937), result);
|
||||||
|
time2 = get_timestamp();
|
||||||
|
INFO("found nearest element to (49.0316,2.6937): " << (found_nearest ? "yes" : "no") << " in " << (time2-time1) << "s at (" << result.lat1/100000. << "," << result.lon1/100000. << " " << result.lat2/100000. << "," << result.lon2/100000. << ")");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
//Read-only operation for queries
|
||||||
|
explicit StaticRTree(
|
||||||
|
const char * node_filename,
|
||||||
|
const char * leaf_filename
|
||||||
|
) : m_leaf_node_filename(leaf_filename) {
|
||||||
|
//INFO("Loading nodes: " << node_filename);
|
||||||
|
//INFO("opening leafs: " << leaf_filename);
|
||||||
|
//open tree node file and load into RAM.
|
||||||
|
std::ifstream tree_node_file(node_filename, std::ios::binary);
|
||||||
|
uint32_t tree_size = 0;
|
||||||
|
tree_node_file.read((char*)&tree_size, sizeof(uint32_t));
|
||||||
|
//INFO("reading " << tree_size << " tree nodes in " << (sizeof(TreeNode)*tree_size) << " bytes");
|
||||||
|
m_search_tree.resize(tree_size);
|
||||||
|
tree_node_file.read((char*)&m_search_tree[0], sizeof(TreeNode)*tree_size);
|
||||||
|
tree_node_file.close();
|
||||||
|
|
||||||
|
//open leaf node file and store thread specific pointer
|
||||||
|
std::ifstream leaf_node_file(leaf_filename, std::ios::binary);
|
||||||
|
leaf_node_file.read((char*)&m_element_count, sizeof(uint64_t));
|
||||||
|
leaf_node_file.close();
|
||||||
|
|
||||||
|
//INFO( tree_size << " nodes in search tree");
|
||||||
|
//INFO( m_element_count << " elements in leafs");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
inline void FindKNearestPhantomNodesForCoordinate(
|
||||||
|
const _Coordinate & location,
|
||||||
|
const unsigned zoom_level,
|
||||||
|
const unsigned candidate_count,
|
||||||
|
std::vector<std::pair<PhantomNode, double> > & result_vector
|
||||||
|
) const {
|
||||||
|
|
||||||
|
bool ignore_tiny_components = (zoom_level <= 14);
|
||||||
|
DataT nearest_edge;
|
||||||
|
|
||||||
|
uint32_t io_count = 0;
|
||||||
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
|
INFO("searching for coordinate " << input_coordinate);
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
|
_Coordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||||
|
|
||||||
|
//initialize queue with root element
|
||||||
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
|
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||||
|
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||||
|
|
||||||
|
while(!traversal_queue.empty()) {
|
||||||
|
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||||
|
|
||||||
|
++explored_tree_nodes_count;
|
||||||
|
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||||
|
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||||
|
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||||
|
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||||
|
if (current_tree_node.child_is_on_disk) {
|
||||||
|
LeafNode current_leaf_node;
|
||||||
|
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||||
|
++io_count;
|
||||||
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
|
DataT & current_edge = current_leaf_node.objects[i];
|
||||||
|
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double current_ratio = 0.;
|
||||||
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
|
input_coordinate,
|
||||||
|
_Coordinate(current_edge.lat1, current_edge.lon1),
|
||||||
|
_Coordinate(current_edge.lat2, current_edge.lon2),
|
||||||
|
nearest,
|
||||||
|
¤t_ratio
|
||||||
|
);
|
||||||
|
|
||||||
|
if(
|
||||||
|
current_perpendicular_distance < min_dist
|
||||||
|
&& !DoubleEpsilonCompare(
|
||||||
|
current_perpendicular_distance,
|
||||||
|
min_dist
|
||||||
|
)
|
||||||
|
) { //found a new minimum
|
||||||
|
min_dist = current_perpendicular_distance;
|
||||||
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
|
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||||
|
result_phantom_node.weight1 = current_edge.weight;
|
||||||
|
result_phantom_node.weight2 = INT_MAX;
|
||||||
|
result_phantom_node.location = nearest;
|
||||||
|
current_start_coordinate.lat = current_edge.lat1;
|
||||||
|
current_start_coordinate.lon = current_edge.lon1;
|
||||||
|
current_end_coordinate.lat = current_edge.lat2;
|
||||||
|
current_end_coordinate.lon = current_edge.lon2;
|
||||||
|
nearest_edge = current_edge;
|
||||||
|
found_a_nearest_edge = true;
|
||||||
|
} else if(
|
||||||
|
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||||
|
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||||
|
&& CoordinatesAreEquivalent(
|
||||||
|
current_start_coordinate,
|
||||||
|
_Coordinate(
|
||||||
|
current_edge.lat1,
|
||||||
|
current_edge.lon1
|
||||||
|
),
|
||||||
|
_Coordinate(
|
||||||
|
current_edge.lat2,
|
||||||
|
current_edge.lon2
|
||||||
|
),
|
||||||
|
current_end_coordinate
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode);
|
||||||
|
result_phantom_node.weight2 = current_edge.weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//traverse children, prune if global mindist is smaller than local one
|
||||||
|
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||||
|
const int32_t child_id = current_tree_node.children[i];
|
||||||
|
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||||
|
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||||
|
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||||
|
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||||
|
if( current_min_max_dist < min_max_dist ) {
|
||||||
|
min_max_dist = current_min_max_dist;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_max_dist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_dist) { //upward pruning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double ratio = (found_a_nearest_edge ?
|
||||||
|
std::min(1., ApproximateDistance(_Coordinate(nearest_edge.lat1, nearest_edge.lon1),
|
||||||
|
result_phantom_node.location)/ApproximateDistance(_Coordinate(nearest_edge.lat1, nearest_edge.lon1), _Coordinate(nearest_edge.lat2, nearest_edge.lon2))
|
||||||
|
) : 0
|
||||||
|
);
|
||||||
|
result_phantom_node.weight1 *= ratio;
|
||||||
|
if(INT_MAX != result_phantom_node.weight2) {
|
||||||
|
result_phantom_node.weight2 *= (1.-ratio);
|
||||||
|
}
|
||||||
|
result_phantom_node.ratio = ratio;
|
||||||
|
|
||||||
|
//Hack to fix rounding errors and wandering via nodes.
|
||||||
|
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||||
|
result_phantom_node.location.lon = input_coordinate.lon;
|
||||||
|
}
|
||||||
|
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||||
|
result_phantom_node.location.lat = input_coordinate.lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO("mindist: " << min_dist << ", io's: " << io_count << ", nodes: " << explored_tree_nodes_count << ", loc: " << result_phantom_node.location << ", ratio: " << ratio << ", id: " << result_phantom_node.edgeBasedNode);
|
||||||
|
INFO("bidirected: " << (result_phantom_node.isBidirected() ? "yes" : "no") );
|
||||||
|
return found_a_nearest_edge;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
bool FindPhantomNodeForCoordinate(
|
||||||
|
const _Coordinate & input_coordinate,
|
||||||
|
PhantomNode & result_phantom_node,
|
||||||
|
const unsigned zoom_level
|
||||||
|
) {
|
||||||
|
|
||||||
|
bool ignore_tiny_components = (zoom_level <= 14);
|
||||||
|
DataT nearest_edge;
|
||||||
|
|
||||||
|
uint32_t io_count = 0;
|
||||||
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
|
//INFO("searching for coordinate " << input_coordinate);
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
bool found_a_nearest_edge = false;
|
||||||
|
|
||||||
|
_Coordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||||
|
|
||||||
|
//initialize queue with root element
|
||||||
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
|
double current_min_dist = m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||||
|
traversal_queue.push(
|
||||||
|
QueryCandidate(0, current_min_dist)
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(
|
||||||
|
FLT_EPSILON > (0. - traversal_queue.top().min_dist),
|
||||||
|
"Root element in NN Search has min dist != 0."
|
||||||
|
);
|
||||||
|
|
||||||
|
while(!traversal_queue.empty()) {
|
||||||
|
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||||
|
|
||||||
|
++explored_tree_nodes_count;
|
||||||
|
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||||
|
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||||
|
if( !prune_downward && !prune_upward ) { //downward pruning
|
||||||
|
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||||
|
if (current_tree_node.child_is_on_disk) {
|
||||||
|
LeafNode current_leaf_node;
|
||||||
|
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||||
|
++io_count;
|
||||||
|
//INFO("checking " << current_leaf_node.object_count << " elements");
|
||||||
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
|
DataT & current_edge = current_leaf_node.objects[i];
|
||||||
|
if(ignore_tiny_components && current_edge.belongsToTinyComponent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(current_edge.isIgnored()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
double current_ratio = 0.;
|
||||||
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
|
input_coordinate,
|
||||||
|
_Coordinate(current_edge.lat1, current_edge.lon1),
|
||||||
|
_Coordinate(current_edge.lat2, current_edge.lon2),
|
||||||
|
nearest,
|
||||||
|
¤t_ratio
|
||||||
|
);
|
||||||
|
|
||||||
|
//INFO("[" << current_edge.id << "] (" << current_edge.lat1/100000. << "," << current_edge.lon1/100000. << ")==(" << current_edge.lat2/100000. << "," << current_edge.lon2/100000. << ") at distance " << current_perpendicular_distance << " min dist: " << min_dist
|
||||||
|
// << ", ratio " << current_ratio
|
||||||
|
// );
|
||||||
|
|
||||||
|
if(
|
||||||
|
current_perpendicular_distance < min_dist
|
||||||
|
&& !DoubleEpsilonCompare(
|
||||||
|
current_perpendicular_distance,
|
||||||
|
min_dist
|
||||||
|
)
|
||||||
|
) { //found a new minimum
|
||||||
|
min_dist = current_perpendicular_distance;
|
||||||
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
|
result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID;
|
||||||
|
result_phantom_node.weight1 = current_edge.weight;
|
||||||
|
result_phantom_node.weight2 = INT_MAX;
|
||||||
|
result_phantom_node.location = nearest;
|
||||||
|
current_start_coordinate.lat = current_edge.lat1;
|
||||||
|
current_start_coordinate.lon = current_edge.lon1;
|
||||||
|
current_end_coordinate.lat = current_edge.lat2;
|
||||||
|
current_end_coordinate.lon = current_edge.lon2;
|
||||||
|
nearest_edge = current_edge;
|
||||||
|
found_a_nearest_edge = true;
|
||||||
|
} else if(
|
||||||
|
DoubleEpsilonCompare(current_perpendicular_distance, min_dist) &&
|
||||||
|
1 == abs(current_edge.id - result_phantom_node.edgeBasedNode )
|
||||||
|
&& CoordinatesAreEquivalent(
|
||||||
|
current_start_coordinate,
|
||||||
|
_Coordinate(
|
||||||
|
current_edge.lat1,
|
||||||
|
current_edge.lon1
|
||||||
|
),
|
||||||
|
_Coordinate(
|
||||||
|
current_edge.lat2,
|
||||||
|
current_edge.lon2
|
||||||
|
),
|
||||||
|
current_end_coordinate
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different");
|
||||||
|
//INFO("found bidirected edge on nodes " << current_edge.id << " and " << result_phantom_node.edgeBasedNode);
|
||||||
|
result_phantom_node.weight2 = current_edge.weight;
|
||||||
|
if(current_edge.id < result_phantom_node.edgeBasedNode) {
|
||||||
|
result_phantom_node.edgeBasedNode = current_edge.id;
|
||||||
|
std::swap(result_phantom_node.weight1, result_phantom_node.weight2);
|
||||||
|
std::swap(current_end_coordinate, current_start_coordinate);
|
||||||
|
// INFO("case 2");
|
||||||
|
}
|
||||||
|
//INFO("w1: " << result_phantom_node.weight1 << ", w2: " << result_phantom_node.weight2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//traverse children, prune if global mindist is smaller than local one
|
||||||
|
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||||
|
const int32_t child_id = current_tree_node.children[i];
|
||||||
|
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||||
|
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||||
|
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||||
|
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||||
|
if( current_min_max_dist < min_max_dist ) {
|
||||||
|
min_max_dist = current_min_max_dist;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_max_dist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_dist) { //upward pruning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const double ratio = (found_a_nearest_edge ?
|
||||||
|
std::min(1., ApproximateDistance(current_start_coordinate,
|
||||||
|
result_phantom_node.location)/ApproximateDistance(current_start_coordinate, current_end_coordinate)
|
||||||
|
) : 0
|
||||||
|
);
|
||||||
|
result_phantom_node.weight1 *= ratio;
|
||||||
|
if(INT_MAX != result_phantom_node.weight2) {
|
||||||
|
result_phantom_node.weight2 *= (1.-ratio);
|
||||||
|
}
|
||||||
|
result_phantom_node.ratio = ratio;
|
||||||
|
|
||||||
|
//Hack to fix rounding errors and wandering via nodes.
|
||||||
|
if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) {
|
||||||
|
result_phantom_node.location.lon = input_coordinate.lon;
|
||||||
|
}
|
||||||
|
if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) {
|
||||||
|
result_phantom_node.location.lat = input_coordinate.lat;
|
||||||
|
}
|
||||||
|
|
||||||
|
// INFO("start: (" << nearest_edge.lat1 << "," << nearest_edge.lon1 << "), end: (" << nearest_edge.lat2 << "," << nearest_edge.lon2 << ")" );
|
||||||
|
// INFO("mindist: " << min_dist << ", io's: " << io_count << ", nodes: " << explored_tree_nodes_count << ", loc: " << result_phantom_node.location << ", ratio: " << ratio << ", id: " << result_phantom_node.edgeBasedNode);
|
||||||
|
// INFO("weight1: " << result_phantom_node.weight1 << ", weight2: " << result_phantom_node.weight2);
|
||||||
|
// INFO("bidirected: " << (result_phantom_node.isBidirected() ? "yes" : "no") );
|
||||||
|
// INFO("NameID: " << result_phantom_node.nodeBasedEdgeNameID);
|
||||||
|
return found_a_nearest_edge;
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
//Nearest-Neighbor query with the Roussopoulos et al. algorithm [2]
|
||||||
|
inline bool NearestNeighbor(const _Coordinate & input_coordinate, DataT & result_element) {
|
||||||
|
uint32_t io_count = 0;
|
||||||
|
uint32_t explored_tree_nodes_count = 0;
|
||||||
|
INFO("searching for coordinate " << input_coordinate);
|
||||||
|
double min_dist = DBL_MAX;
|
||||||
|
double min_max_dist = DBL_MAX;
|
||||||
|
bool found_return_value = false;
|
||||||
|
|
||||||
|
//initialize queue with root element
|
||||||
|
std::priority_queue<QueryCandidate> traversal_queue;
|
||||||
|
traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate)));
|
||||||
|
BOOST_ASSERT_MSG(FLT_EPSILON > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0.");
|
||||||
|
|
||||||
|
while(!traversal_queue.empty()) {
|
||||||
|
const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop();
|
||||||
|
|
||||||
|
++explored_tree_nodes_count;
|
||||||
|
|
||||||
|
// INFO("popped node " << current_query_node.node_id << " at distance " << current_query_node.min_dist);
|
||||||
|
bool prune_downward = (current_query_node.min_dist >= min_max_dist);
|
||||||
|
bool prune_upward = (current_query_node.min_dist >= min_dist);
|
||||||
|
// INFO(" up prune: " << (prune_upward ? "y" : "n" ));
|
||||||
|
// INFO(" down prune: " << (prune_downward ? "y" : "n" ));
|
||||||
|
if( prune_downward || prune_upward ) { //downward pruning
|
||||||
|
// INFO(" pruned node " << current_query_node.node_id << " because " << current_query_node.min_dist << "<" << min_max_dist);
|
||||||
|
} else {
|
||||||
|
TreeNode & current_tree_node = m_search_tree[current_query_node.node_id];
|
||||||
|
if (current_tree_node.child_is_on_disk) {
|
||||||
|
// INFO(" Fetching child from disk for id: " << current_query_node.node_id);
|
||||||
|
LeafNode current_leaf_node;
|
||||||
|
LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node);
|
||||||
|
++io_count;
|
||||||
|
double ratio = 0.;
|
||||||
|
_Coordinate nearest;
|
||||||
|
for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) {
|
||||||
|
DataT & current_object = current_leaf_node.objects[i];
|
||||||
|
double current_perpendicular_distance = ComputePerpendicularDistance(
|
||||||
|
input_coordinate,
|
||||||
|
_Coordinate(current_object.lat1, current_object.lon1),
|
||||||
|
_Coordinate(current_object.lat2, current_object.lon2),
|
||||||
|
nearest,
|
||||||
|
&ratio
|
||||||
|
);
|
||||||
|
|
||||||
|
if(current_perpendicular_distance < min_dist && !DoubleEpsilonCompare(current_perpendicular_distance, min_dist)) { //found a new minimum
|
||||||
|
min_dist = current_perpendicular_distance;
|
||||||
|
result_element = current_object;
|
||||||
|
found_return_value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//traverse children, prune if global mindist is smaller than local one
|
||||||
|
// INFO(" Checking " << current_tree_node.child_count << " children of node " << current_query_node.node_id);
|
||||||
|
for (uint32_t i = 0; i < current_tree_node.child_count; ++i) {
|
||||||
|
const int32_t child_id = current_tree_node.children[i];
|
||||||
|
TreeNode & child_tree_node = m_search_tree[child_id];
|
||||||
|
RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||||
|
const double current_min_dist = child_rectangle.GetMinDist(input_coordinate);
|
||||||
|
const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate);
|
||||||
|
if( current_min_max_dist < min_max_dist ) {
|
||||||
|
min_max_dist = current_min_max_dist;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_max_dist) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (current_min_dist > min_dist) { //upward pruning
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// INFO(" pushing node " << child_id << " at distance " << current_min_dist);
|
||||||
|
traversal_queue.push(QueryCandidate(child_id, current_min_dist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
INFO("mindist: " << min_dist << ", io's: " << io_count << ", touched nodes: " << explored_tree_nodes_count);
|
||||||
|
return found_return_value;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
private:
|
||||||
|
inline void LoadLeafFromDisk(const uint32_t leaf_id, LeafNode& result_node) {
|
||||||
|
if(!thread_local_rtree_stream.get() || !thread_local_rtree_stream->is_open()) {
|
||||||
|
thread_local_rtree_stream.reset(
|
||||||
|
new std::ifstream(
|
||||||
|
m_leaf_node_filename.c_str(),
|
||||||
|
std::ios::in | std::ios::binary
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if(!thread_local_rtree_stream->good()) {
|
||||||
|
thread_local_rtree_stream->clear(std::ios::goodbit);
|
||||||
|
DEBUG("Resetting stale filestream");
|
||||||
|
}
|
||||||
|
uint64_t seek_pos = sizeof(uint64_t) + leaf_id*sizeof(LeafNode);
|
||||||
|
thread_local_rtree_stream->seekg(seek_pos);
|
||||||
|
thread_local_rtree_stream->read((char *)&result_node, sizeof(LeafNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double ComputePerpendicularDistance(
|
||||||
|
const _Coordinate& inputPoint,
|
||||||
|
const _Coordinate& source,
|
||||||
|
const _Coordinate& target,
|
||||||
|
_Coordinate& nearest, double *r) const {
|
||||||
|
const double x = static_cast<double>(inputPoint.lat);
|
||||||
|
const double y = static_cast<double>(inputPoint.lon);
|
||||||
|
const double a = static_cast<double>(source.lat);
|
||||||
|
const double b = static_cast<double>(source.lon);
|
||||||
|
const double c = static_cast<double>(target.lat);
|
||||||
|
const double d = static_cast<double>(target.lon);
|
||||||
|
double p,q,mX,nY;
|
||||||
|
if(fabs(a-c) > FLT_EPSILON){
|
||||||
|
const double m = (d-b)/(c-a); // slope
|
||||||
|
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||||
|
p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m);
|
||||||
|
q = b + m*(p - a);
|
||||||
|
} else {
|
||||||
|
p = c;
|
||||||
|
q = y;
|
||||||
|
}
|
||||||
|
nY = (d*p - c*q)/(a*d - b*c);
|
||||||
|
mX = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need
|
||||||
|
// not calculate the explicit values of m an n as we
|
||||||
|
// are just interested in the ratio
|
||||||
|
if(std::isnan(mX)) {
|
||||||
|
*r = (target == inputPoint) ? 1. : 0.;
|
||||||
|
} else {
|
||||||
|
*r = mX;
|
||||||
|
}
|
||||||
|
if(*r<=0.){
|
||||||
|
nearest.lat = source.lat;
|
||||||
|
nearest.lon = source.lon;
|
||||||
|
return ((b - y)*(b - y) + (a - x)*(a - x));
|
||||||
|
// return std::sqrt(((b - y)*(b - y) + (a - x)*(a - x)));
|
||||||
|
} else if(*r >= 1.){
|
||||||
|
nearest.lat = target.lat;
|
||||||
|
nearest.lon = target.lon;
|
||||||
|
return ((d - y)*(d - y) + (c - x)*(c - x));
|
||||||
|
// return std::sqrt(((d - y)*(d - y) + (c - x)*(c - x)));
|
||||||
|
}
|
||||||
|
// point lies in between
|
||||||
|
nearest.lat = p;
|
||||||
|
nearest.lon = q;
|
||||||
|
// return std::sqrt((p-x)*(p-x) + (q-y)*(q-y));
|
||||||
|
return (p-x)*(p-x) + (q-y)*(q-y);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool CoordinatesAreEquivalent(const _Coordinate & a, const _Coordinate & b, const _Coordinate & c, const _Coordinate & d) const {
|
||||||
|
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DoubleEpsilonCompare(const double d1, const double d2) const {
|
||||||
|
return (std::fabs(d1 - d2) < FLT_EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//[1] "On Packing R-Trees"; I. Kamel, C. Faloutsos; 1993; DOI: 10.1145/170088.170403
|
||||||
|
//[2] "Nearest Neighbor Queries", N. Roussopulos et al; 1995; DOI: 10.1145/223784.223794
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* STATICRTREE_H_ */
|
@ -28,8 +28,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/PhantomNodes.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/PhantomNodes.h"
|
||||||
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include "../Plugins/RawRouteData.h"
|
#include "../Plugins/RawRouteData.h"
|
||||||
@ -42,13 +43,12 @@ struct _DescriptorConfig {
|
|||||||
unsigned short z;
|
unsigned short z;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class SearchEngineT>
|
|
||||||
class BaseDescriptor {
|
class BaseDescriptor {
|
||||||
public:
|
public:
|
||||||
BaseDescriptor() { }
|
BaseDescriptor() { }
|
||||||
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
virtual ~BaseDescriptor() { }
|
virtual ~BaseDescriptor() { }
|
||||||
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) = 0;
|
virtual void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) = 0;
|
||||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
|
|||||||
pc.printUnencodedString(pathDescription, output);
|
pc.printUnencodedString(pathDescription, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) {
|
void DescriptionFactory::Run(const SearchEngine &sEngine, const unsigned zoomLevel) {
|
||||||
|
|
||||||
if(0 == pathDescription.size())
|
if(0 == pathDescription.size())
|
||||||
return;
|
return;
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#include "../Algorithms/DouglasPeucker.h"
|
#include "../Algorithms/DouglasPeucker.h"
|
||||||
#include "../Algorithms/PolylineCompressor.h"
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
#include "../DataStructures/Coordinate.h"
|
#include "../DataStructures/Coordinate.h"
|
||||||
#include "../DataStructures/QueryEdge.h"
|
|
||||||
#include "../DataStructures/SearchEngine.h"
|
#include "../DataStructures/SearchEngine.h"
|
||||||
#include "../DataStructures/SegmentInformation.h"
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
#include "../DataStructures/TurnInstructions.h"
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
@ -40,8 +39,6 @@ class DescriptionFactory {
|
|||||||
PolylineCompressor pc;
|
PolylineCompressor pc;
|
||||||
PhantomNode startPhantom, targetPhantom;
|
PhantomNode startPhantom, targetPhantom;
|
||||||
|
|
||||||
typedef SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > SearchEngineT;
|
|
||||||
|
|
||||||
double DegreeToRadian(const double degree) const;
|
double DegreeToRadian(const double degree) const;
|
||||||
double RadianToDegree(const double degree) const;
|
double RadianToDegree(const double degree) const;
|
||||||
public:
|
public:
|
||||||
@ -73,7 +70,7 @@ public:
|
|||||||
void SetStartSegment(const PhantomNode & startPhantom);
|
void SetStartSegment(const PhantomNode & startPhantom);
|
||||||
void SetEndSegment(const PhantomNode & startPhantom);
|
void SetEndSegment(const PhantomNode & startPhantom);
|
||||||
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
||||||
void Run(const SearchEngineT &sEngine, const unsigned zoomLevel);
|
void Run(const SearchEngine &sEngine, const unsigned zoomLevel);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DESCRIPTIONFACTORY_H_ */
|
#endif /* DESCRIPTIONFACTORY_H_ */
|
||||||
|
@ -24,8 +24,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
template<class SearchEngineT>
|
class GPXDescriptor : public BaseDescriptor{
|
||||||
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
|
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
_DescriptorConfig config;
|
||||||
_Coordinate current;
|
_Coordinate current;
|
||||||
@ -33,7 +32,7 @@ private:
|
|||||||
std::string tmp;
|
std::string tmp;
|
||||||
public:
|
public:
|
||||||
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
|
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
||||||
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
reply.content += "<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||||
|
@ -34,8 +34,7 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../Util/Azimuth.h"
|
#include "../Util/Azimuth.h"
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
template<class SearchEngineT>
|
class JSONDescriptor : public BaseDescriptor{
|
||||||
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
_DescriptorConfig config;
|
||||||
DescriptionFactory descriptionFactory;
|
DescriptionFactory descriptionFactory;
|
||||||
@ -68,7 +67,7 @@ public:
|
|||||||
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
|
||||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
||||||
|
|
||||||
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine) {
|
void Run(http::Reply & reply, const RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngine &sEngine) {
|
||||||
|
|
||||||
WriteHeaderToOutput(reply.content);
|
WriteHeaderToOutput(reply.content);
|
||||||
|
|
||||||
@ -246,7 +245,7 @@ public:
|
|||||||
reply.content += "}";
|
reply.content += "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngineT &sEngine, RouteNames & routeNames) {
|
void GetRouteNames(std::vector<Segment> & shortestSegments, std::vector<Segment> & alternativeSegments, const SearchEngine &sEngine, RouteNames & routeNames) {
|
||||||
/*** extract names for both alternatives ***/
|
/*** extract names for both alternatives ***/
|
||||||
|
|
||||||
Segment shortestSegment1, shortestSegment2;
|
Segment shortestSegment1, shortestSegment2;
|
||||||
@ -304,7 +303,7 @@ public:
|
|||||||
"\"status\":";
|
"\"status\":";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngineT &sEngine, std::vector<Segment> & segmentVector) {
|
inline void BuildTextualDescription(DescriptionFactory & descriptionFactory, http::Reply & reply, const int lengthOfRoute, const SearchEngine &sEngine, std::vector<Segment> & segmentVector) {
|
||||||
//Segment information has following format:
|
//Segment information has following format:
|
||||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||||
|
@ -257,8 +257,8 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const
|
|||||||
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool));
|
||||||
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool));
|
||||||
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
|
fout.write((char*)&edgeIT->isContraFlow, sizeof(bool));
|
||||||
|
++usedEdgeCounter;
|
||||||
}
|
}
|
||||||
++usedEdgeCounter;
|
|
||||||
++edgeIT;
|
++edgeIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
#ifndef EXTRACTIONCONTAINERS_H_
|
#ifndef EXTRACTIONCONTAINERS_H_
|
||||||
#define EXTRACTIONCONTAINERS_H_
|
#define EXTRACTIONCONTAINERS_H_
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <stxxl.h>
|
|
||||||
|
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
#include "../DataStructures/TimingUtil.h"
|
#include "../DataStructures/TimingUtil.h"
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <stxxl.h>
|
||||||
|
|
||||||
class ExtractionContainers {
|
class ExtractionContainers {
|
||||||
public:
|
public:
|
||||||
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
typedef stxxl::vector<NodeID> STXXLNodeIDVector;
|
||||||
|
@ -76,7 +76,7 @@ inline bool PBFParser::ReadHeader() {
|
|||||||
else if ( "DenseNodes" == feature ) {
|
else if ( "DenseNodes" == feature ) {
|
||||||
supported = true;
|
supported = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !supported ) {
|
if ( !supported ) {
|
||||||
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
|
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
@ -155,22 +155,19 @@ inline bool PBFParser::Parse() {
|
|||||||
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
||||||
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
|
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
|
||||||
int denseTagIndex = 0;
|
int denseTagIndex = 0;
|
||||||
int m_lastDenseID = 0;
|
int64_t m_lastDenseID = 0;
|
||||||
int m_lastDenseLatitude = 0;
|
int64_t m_lastDenseLatitude = 0;
|
||||||
int m_lastDenseLongitude = 0;
|
int64_t m_lastDenseLongitude = 0;
|
||||||
|
|
||||||
ImportNode n;
|
|
||||||
std::vector<ImportNode> extracted_nodes_vector;
|
|
||||||
const int number_of_nodes = dense.id_size();
|
const int number_of_nodes = dense.id_size();
|
||||||
extracted_nodes_vector.reserve(number_of_nodes);
|
std::vector<ImportNode> extracted_nodes_vector(number_of_nodes);
|
||||||
for(int i = 0; i < number_of_nodes; ++i) {
|
for(int i = 0; i < number_of_nodes; ++i) {
|
||||||
n.Clear();
|
|
||||||
m_lastDenseID += dense.id( i );
|
m_lastDenseID += dense.id( i );
|
||||||
m_lastDenseLatitude += dense.lat( i );
|
m_lastDenseLatitude += dense.lat( i );
|
||||||
m_lastDenseLongitude += dense.lon( i );
|
m_lastDenseLongitude += dense.lon( i );
|
||||||
n.id = m_lastDenseID;
|
extracted_nodes_vector[i].id = m_lastDenseID;
|
||||||
n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
|
extracted_nodes_vector[i].lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lat_offset() ) / NANO;
|
||||||
n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
extracted_nodes_vector[i].lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
|
||||||
while (denseTagIndex < dense.keys_vals_size()) {
|
while (denseTagIndex < dense.keys_vals_size()) {
|
||||||
const int tagValue = dense.keys_vals( denseTagIndex );
|
const int tagValue = dense.keys_vals( denseTagIndex );
|
||||||
if( 0==tagValue ) {
|
if( 0==tagValue ) {
|
||||||
@ -180,10 +177,9 @@ inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
|
|||||||
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
|
const int keyValue = dense.keys_vals ( denseTagIndex+1 );
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
|
||||||
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
|
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
|
||||||
n.keyVals.Add(key, value);
|
extracted_nodes_vector[i].keyVals.Add(key, value);
|
||||||
denseTagIndex += 2;
|
denseTagIndex += 2;
|
||||||
}
|
}
|
||||||
extracted_nodes_vector.push_back(n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma omp parallel for schedule ( guided )
|
#pragma omp parallel for schedule ( guided )
|
||||||
@ -292,37 +288,33 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void PBFParser::parseWay(_ThreadData * threadData) {
|
inline void PBFParser::parseWay(_ThreadData * threadData) {
|
||||||
ExtractionWay w;
|
|
||||||
std::vector<ExtractionWay> waysToParse;
|
|
||||||
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
|
const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size();
|
||||||
waysToParse.reserve(number_of_ways);
|
std::vector<ExtractionWay> parsed_way_vector(number_of_ways);
|
||||||
for(int i = 0; i < number_of_ways; ++i) {
|
for(int i = 0; i < number_of_ways; ++i) {
|
||||||
w.Clear();
|
|
||||||
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
|
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
|
||||||
w.id = inputWay.id();
|
parsed_way_vector[i].id = inputWay.id();
|
||||||
unsigned pathNode(0);
|
unsigned pathNode(0);
|
||||||
const int number_of_referenced_nodes = inputWay.refs_size();
|
const int number_of_referenced_nodes = inputWay.refs_size();
|
||||||
for(int i = 0; i < number_of_referenced_nodes; ++i) {
|
for(int j = 0; j < number_of_referenced_nodes; ++j) {
|
||||||
pathNode += inputWay.refs(i);
|
pathNode += inputWay.refs(j);
|
||||||
w.path.push_back(pathNode);
|
parsed_way_vector[i].path.push_back(pathNode);
|
||||||
}
|
}
|
||||||
assert(inputWay.keys_size() == inputWay.vals_size());
|
assert(inputWay.keys_size() == inputWay.vals_size());
|
||||||
const int number_of_keys = inputWay.keys_size();
|
const int number_of_keys = inputWay.keys_size();
|
||||||
for(int i = 0; i < number_of_keys; ++i) {
|
for(int j = 0; j < number_of_keys; ++j) {
|
||||||
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i));
|
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(j));
|
||||||
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i));
|
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(j));
|
||||||
w.keyVals.Add(key, val);
|
parsed_way_vector[i].keyVals.Add(key, val);
|
||||||
}
|
}
|
||||||
waysToParse.push_back(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 = waysToParse[i];
|
ExtractionWay & w = parsed_way_vector[i];
|
||||||
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_FOREACH(ExtractionWay & w, waysToParse) {
|
BOOST_FOREACH(ExtractionWay & w, parsed_way_vector) {
|
||||||
extractor_callbacks->wayFunction(w);
|
extractor_callbacks->wayFunction(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +415,7 @@ inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData)
|
|||||||
if(stream.eof()) {
|
if(stream.eof()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int size = threadData->PBFBlobHeader.datasize();
|
const int size = threadData->PBFBlobHeader.datasize();
|
||||||
if ( size < 0 || size > MAX_BLOB_SIZE ) {
|
if ( size < 0 || size > MAX_BLOB_SIZE ) {
|
||||||
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
std::cerr << "[error] invalid Blob size:" << size << std::endl;
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
/*
|
/*
|
||||||
open source routing machine
|
open source routing machine
|
||||||
Copyright (C) Dennis Luxen, others 2010
|
Copyright (C) Dennis Luxen, others 2010
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU AFFERO General Public License as published by
|
it under the terms of the GNU AFFERO General Public License as published by
|
||||||
the Free Software Foundation; either version 3 of the License, or
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
any later version.
|
any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
@ -21,6 +21,13 @@
|
|||||||
#ifndef PBFPARSER_H_
|
#ifndef PBFPARSER_H_
|
||||||
#define PBFPARSER_H_
|
#define PBFPARSER_H_
|
||||||
|
|
||||||
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../DataStructures/ConcurrentQueue.h"
|
||||||
|
#include "../Util/MachineInfo.h"
|
||||||
|
#include "../Util/OpenMPWrapper.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include "BaseParser.h"
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
@ -30,44 +37,38 @@
|
|||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "../typedefs.h"
|
|
||||||
#include "../DataStructures/HashTable.h"
|
|
||||||
#include "../DataStructures/ConcurrentQueue.h"
|
|
||||||
#include "../Util/MachineInfo.h"
|
|
||||||
#include "../Util/OpenMPWrapper.h"
|
|
||||||
|
|
||||||
#include "BaseParser.h"
|
|
||||||
|
|
||||||
class PBFParser : public BaseParser {
|
class PBFParser : public BaseParser {
|
||||||
|
|
||||||
enum EntityType {
|
enum EntityType {
|
||||||
TypeNode = 1,
|
TypeNode = 1,
|
||||||
TypeWay = 2,
|
TypeWay = 2,
|
||||||
TypeRelation = 4,
|
TypeRelation = 4,
|
||||||
TypeDenseNode = 8
|
TypeDenseNode = 8
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
struct _ThreadData {
|
struct _ThreadData {
|
||||||
int currentGroupID;
|
int currentGroupID;
|
||||||
int currentEntityID;
|
int currentEntityID;
|
||||||
short entityTypeIndicator;
|
short entityTypeIndicator;
|
||||||
|
|
||||||
OSMPBF::BlobHeader PBFBlobHeader;
|
OSMPBF::BlobHeader PBFBlobHeader;
|
||||||
OSMPBF::Blob PBFBlob;
|
OSMPBF::Blob PBFBlob;
|
||||||
|
|
||||||
OSMPBF::HeaderBlock PBFHeaderBlock;
|
OSMPBF::HeaderBlock PBFHeaderBlock;
|
||||||
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
|
OSMPBF::PrimitiveBlock PBFprimitiveBlock;
|
||||||
|
|
||||||
std::vector<char> charBuffer;
|
std::vector<char> charBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
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();
|
||||||
inline bool Parse();
|
inline bool Parse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void ReadData();
|
inline void ReadData();
|
||||||
inline void ParseData();
|
inline void ParseData();
|
||||||
@ -75,7 +76,7 @@ private:
|
|||||||
inline void parseNode(_ThreadData * );
|
inline void parseNode(_ThreadData * );
|
||||||
inline void parseRelation(_ThreadData * threadData);
|
inline void parseRelation(_ThreadData * threadData);
|
||||||
inline void parseWay(_ThreadData * threadData);
|
inline void parseWay(_ThreadData * threadData);
|
||||||
|
|
||||||
inline void loadGroup(_ThreadData * threadData);
|
inline void loadGroup(_ThreadData * threadData);
|
||||||
inline void loadBlock(_ThreadData * threadData);
|
inline void loadBlock(_ThreadData * threadData);
|
||||||
inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData);
|
inline bool readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData);
|
||||||
@ -83,17 +84,17 @@ private:
|
|||||||
inline bool unpackLZMA(std::fstream &, _ThreadData * );
|
inline bool unpackLZMA(std::fstream &, _ThreadData * );
|
||||||
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ;
|
inline bool readBlob(std::fstream& stream, _ThreadData * threadData) ;
|
||||||
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData);
|
inline bool readNextBlock(std::fstream& stream, _ThreadData * threadData);
|
||||||
|
|
||||||
static const int NANO = 1000 * 1000 * 1000;
|
static const int NANO = 1000 * 1000 * 1000;
|
||||||
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
static const int MAX_BLOB_HEADER_SIZE = 64 * 1024;
|
||||||
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
static const int MAX_BLOB_SIZE = 32 * 1024 * 1024;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/* counting the number of read blocks and groups */
|
/* counting the number of read blocks and groups */
|
||||||
unsigned groupCount;
|
unsigned groupCount;
|
||||||
unsigned blockCount;
|
unsigned blockCount;
|
||||||
#endif
|
#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;
|
||||||
};
|
};
|
||||||
|
@ -21,13 +21,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef LOCATEPLUGIN_H_
|
#ifndef LOCATEPLUGIN_H_
|
||||||
#define LOCATEPLUGIN_H_
|
#define LOCATEPLUGIN_H_
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
#include "RouteParameters.h"
|
||||||
#include "../Util/StringUtil.h"
|
|
||||||
#include "../DataStructures/NodeInformationHelpDesk.h"
|
#include "../DataStructures/NodeInformationHelpDesk.h"
|
||||||
|
#include "../Server/DataStructures/QueryObjectsStorage.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This Plugin locates the nearest node in the road network for a given coordinate.
|
* This Plugin locates the nearest node in the road network for a given coordinate.
|
||||||
|
@ -52,14 +52,14 @@ private:
|
|||||||
StaticGraph<QueryEdge::EdgeData> * graph;
|
StaticGraph<QueryEdge::EdgeData> * graph;
|
||||||
HashTable<std::string, unsigned> descriptorTable;
|
HashTable<std::string, unsigned> descriptorTable;
|
||||||
std::string pluginDescriptorString;
|
std::string pluginDescriptorString;
|
||||||
SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > * searchEngine;
|
SearchEngine * searchEnginePtr;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
|
ViaRoutePlugin(QueryObjectsStorage * objects, std::string psd = "viaroute") : names(objects->names), pluginDescriptorString(psd) {
|
||||||
nodeHelpDesk = objects->nodeHelpDesk;
|
nodeHelpDesk = objects->nodeHelpDesk;
|
||||||
graph = objects->graph;
|
graph = objects->graph;
|
||||||
|
|
||||||
searchEngine = new SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> >(graph, nodeHelpDesk, names);
|
searchEnginePtr = new SearchEngine(graph, nodeHelpDesk, names);
|
||||||
|
|
||||||
descriptorTable.Set("", 0); //default descriptor
|
descriptorTable.Set("", 0); //default descriptor
|
||||||
descriptorTable.Set("json", 0);
|
descriptorTable.Set("json", 0);
|
||||||
@ -67,7 +67,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() {
|
||||||
delete searchEngine;
|
delete searchEnginePtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDescriptor() const { return pluginDescriptorString; }
|
std::string GetDescriptor() const { return pluginDescriptorString; }
|
||||||
@ -101,7 +101,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INFO("Brute force lookup of coordinate " << i);
|
// INFO("Brute force lookup of coordinate " << i);
|
||||||
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
|
searchEnginePtr->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) {
|
||||||
@ -112,10 +112,10 @@ public:
|
|||||||
}
|
}
|
||||||
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
if( ( routeParameters.alternateRoute ) && (1 == rawRoute.segmentEndCoordinates.size()) ) {
|
||||||
// INFO("Checking for alternative paths");
|
// INFO("Checking for alternative paths");
|
||||||
searchEngine->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
searchEnginePtr->alternativePaths(rawRoute.segmentEndCoordinates[0], rawRoute);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
searchEnginePtr->shortestPath(rawRoute.segmentEndCoordinates, rawRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ public:
|
|||||||
reply.status = http::Reply::ok;
|
reply.status = http::Reply::ok;
|
||||||
|
|
||||||
//TODO: Move to member as smart pointer
|
//TODO: Move to member as smart pointer
|
||||||
BaseDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > > * desc;
|
BaseDescriptor * desc;
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += routeParameters.jsonpParameter;
|
reply.content += routeParameters.jsonpParameter;
|
||||||
reply.content += "(";
|
reply.content += "(";
|
||||||
@ -140,15 +140,15 @@ public:
|
|||||||
|
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
case 0:
|
||||||
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
|
desc = new JSONDescriptor();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
desc = new GPXDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
|
desc = new GPXDescriptor();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >();
|
desc = new JSONDescriptor();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ public:
|
|||||||
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
|
// INFO("Number of segments: " << rawRoute.segmentEndCoordinates.size());
|
||||||
desc->SetConfig(descriptorConfig);
|
desc->SetConfig(descriptorConfig);
|
||||||
|
|
||||||
desc->Run(reply, rawRoute, phantomNodes, *searchEngine);
|
desc->Run(reply, rawRoute, phantomNodes, *searchEnginePtr);
|
||||||
if("" != routeParameters.jsonpParameter) {
|
if("" != routeParameters.jsonpParameter) {
|
||||||
reply.content += ")\n";
|
reply.content += ")\n";
|
||||||
}
|
}
|
||||||
|
25
Rakefile
25
Rakefile
@ -4,6 +4,7 @@ require 'digest/sha1'
|
|||||||
require 'cucumber/rake/task'
|
require 'cucumber/rake/task'
|
||||||
require 'sys/proctable'
|
require 'sys/proctable'
|
||||||
|
|
||||||
|
BUILD_FOLDER = 'build'
|
||||||
DATA_FOLDER = 'sandbox'
|
DATA_FOLDER = 'sandbox'
|
||||||
PROFILE = 'bicycle'
|
PROFILE = 'bicycle'
|
||||||
OSRM_PORT = 5000
|
OSRM_PORT = 5000
|
||||||
@ -77,11 +78,13 @@ end
|
|||||||
|
|
||||||
|
|
||||||
desc "Rebuild and run tests."
|
desc "Rebuild and run tests."
|
||||||
task :default => [:build, :cucumber]
|
task :default => [:build]
|
||||||
|
|
||||||
desc "Build using SConsstruct."
|
desc "Build using CMake."
|
||||||
task :build do
|
task :build do
|
||||||
system "scons"
|
Dir.chdir BUILD_FOLDER do
|
||||||
|
system "make"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Setup config files."
|
desc "Setup config files."
|
||||||
@ -99,8 +102,8 @@ desc "Download OSM data."
|
|||||||
task :download => :setup do
|
task :download => :setup do
|
||||||
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
Dir.mkdir "#{DATA_FOLDER}" unless File.exist? "#{DATA_FOLDER}"
|
||||||
puts "Downloading..."
|
puts "Downloading..."
|
||||||
puts "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
puts "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||||
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/openstreetmap/europe/#{osm_data_country}.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
raise "Error while downloading data." unless system "curl http://download.geofabrik.de/europe/#{osm_data_country}-latest.osm.pbf -o #{DATA_FOLDER}/#{osm_data_country}.osm.pbf"
|
||||||
if osm_data_area_bbox
|
if osm_data_area_bbox
|
||||||
puts "Cropping and converting to protobuffer..."
|
puts "Cropping and converting to protobuffer..."
|
||||||
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
raise "Error while cropping data." unless system "osmosis --read-pbf file=#{DATA_FOLDER}/#{osm_data_country}.osm.pbf --bounding-box #{osm_data_area_bbox} --write-pbf file=#{DATA_FOLDER}/#{osm_data_area_name}.osm.pbf omitmetadata=true"
|
||||||
@ -117,9 +120,9 @@ end
|
|||||||
desc "Reprocess OSM data."
|
desc "Reprocess OSM data."
|
||||||
task :process => :setup do
|
task :process => :setup do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
||||||
puts
|
puts
|
||||||
raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions #{PROFILES_FOLDER}/#{PROFILE}.lua"
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -127,14 +130,14 @@ end
|
|||||||
desc "Extract OSM data."
|
desc "Extract OSM data."
|
||||||
task :extract => :setup do
|
task :extract => :setup do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while extracting data." unless system "../osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
|
raise "Error while extracting data." unless system "../#{BUILD_FOLDER}/osrm-extract #{osm_data_area_name}.osm.pbf ../profiles/#{PROFILE}.lua"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Prepare OSM data."
|
desc "Prepare OSM data."
|
||||||
task :prepare => :setup do
|
task :prepare => :setup do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
raise "Error while preparing data." unless system "../osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
|
raise "Error while preparing data." unless system "../#{BUILD_FOLDER}/osrm-prepare #{osm_data_area_name}.osrm #{osm_data_area_name}.osrm.restrictions ../profiles/#{PROFILE}.lua"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -154,7 +157,7 @@ desc "Run the routing server in the terminal. Press Ctrl-C to stop."
|
|||||||
task :run => :setup do
|
task :run => :setup do
|
||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
write_server_ini osm_data_area_name
|
write_server_ini osm_data_area_name
|
||||||
system "../osrm-routed"
|
system "../#{BUILD_FOLDER}/osrm-routed"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -163,7 +166,7 @@ task :up => :setup do
|
|||||||
Dir.chdir DATA_FOLDER do
|
Dir.chdir DATA_FOLDER do
|
||||||
abort("Already up.") if up?
|
abort("Already up.") if up?
|
||||||
write_server_ini osm_data_area_name
|
write_server_ini osm_data_area_name
|
||||||
pipe = IO.popen('../osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log')
|
pipe = IO.popen("../#{BUILD_FOLDER}/osrm-routed 1>>osrm-routed.log 2>>osrm-routed.log")
|
||||||
timeout = 5
|
timeout = 5
|
||||||
(timeout*10).times do
|
(timeout*10).times do
|
||||||
begin
|
begin
|
||||||
|
@ -23,13 +23,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef BASICROUTINGINTERFACE_H_
|
#ifndef BASICROUTINGINTERFACE_H_
|
||||||
#define BASICROUTINGINTERFACE_H_
|
#define BASICROUTINGINTERFACE_H_
|
||||||
|
|
||||||
|
#include "../Plugins/RawRouteData.h"
|
||||||
|
#include "../Util/ContainerUtils.h"
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "../Plugins/RawRouteData.h"
|
#include <stack>
|
||||||
#include "../Util/ContainerUtils.h"
|
|
||||||
|
|
||||||
template<class QueryDataT>
|
template<class QueryDataT>
|
||||||
class BasicRoutingInterface : boost::noncopyable{
|
class BasicRoutingInterface : boost::noncopyable{
|
||||||
@ -42,6 +44,7 @@ public:
|
|||||||
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
inline void RoutingStep(typename QueryDataT::QueryHeap & _forwardHeap, typename QueryDataT::QueryHeap & _backwardHeap, NodeID *middle, int *_upperbound, const int edgeBasedOffset, const bool forwardDirection) const {
|
||||||
const NodeID node = _forwardHeap.DeleteMin();
|
const NodeID node = _forwardHeap.DeleteMin();
|
||||||
const int distance = _forwardHeap.GetKey(node);
|
const int distance = _forwardHeap.GetKey(node);
|
||||||
|
//INFO("Settled (" << _forwardHeap.GetData( node ).parent << "," << node << ")=" << distance);
|
||||||
if(_backwardHeap.WasInserted(node) ){
|
if(_backwardHeap.WasInserted(node) ){
|
||||||
const int newDistance = _backwardHeap.GetKey(node) + distance;
|
const int newDistance = _backwardHeap.GetKey(node) + distance;
|
||||||
if(newDistance < *_upperbound ){
|
if(newDistance < *_upperbound ){
|
||||||
|
@ -73,18 +73,24 @@ public:
|
|||||||
//insert new starting nodes into forward heap, adjusted by previous distances.
|
//insert new starting nodes into forward heap, adjusted by previous distances.
|
||||||
if(searchFrom1stStartNode) {
|
if(searchFrom1stStartNode) {
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||||
|
INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode);
|
||||||
}
|
INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode << "´, w: " << -phantomNodePair.startPhantom.weight1);
|
||||||
|
}
|
||||||
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
if(phantomNodePair.startPhantom.isBidirected() && searchFrom2ndStartNode) {
|
||||||
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||||
|
INFO("fw1: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
forward_heap2.Insert(phantomNodePair.startPhantom.edgeBasedNode+1, -phantomNodePair.startPhantom.weight2, phantomNodePair.startPhantom.edgeBasedNode+1);
|
||||||
|
INFO("fw2: " << phantomNodePair.startPhantom.edgeBasedNode+1 << "´, w: " << -phantomNodePair.startPhantom.weight2);
|
||||||
}
|
}
|
||||||
|
|
||||||
//insert new backward nodes into backward heap, unadjusted.
|
//insert new backward nodes into backward heap, unadjusted.
|
||||||
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
reverse_heap1.Insert(phantomNodePair.targetPhantom.edgeBasedNode, phantomNodePair.targetPhantom.weight1, phantomNodePair.targetPhantom.edgeBasedNode);
|
||||||
|
INFO("rv1: " << phantomNodePair.targetPhantom.edgeBasedNode << ", w;" << phantomNodePair.targetPhantom.weight1 );
|
||||||
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
if(phantomNodePair.targetPhantom.isBidirected() ) {
|
||||||
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
reverse_heap2.Insert(phantomNodePair.targetPhantom.edgeBasedNode+1, phantomNodePair.targetPhantom.weight2, phantomNodePair.targetPhantom.edgeBasedNode+1);
|
||||||
}
|
INFO("rv2: " << phantomNodePair.targetPhantom.edgeBasedNode+1 << ", w;" << phantomNodePair.targetPhantom.weight2 );
|
||||||
|
}
|
||||||
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
const int forward_offset = phantomNodePair.startPhantom.weight1 + (phantomNodePair.startPhantom.isBidirected() ? phantomNodePair.startPhantom.weight2 : 0);
|
||||||
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
const int reverse_offset = phantomNodePair.targetPhantom.weight1 + (phantomNodePair.targetPhantom.isBidirected() ? phantomNodePair.targetPhantom.weight2 : 0);
|
||||||
|
|
||||||
|
300
SConstruct
300
SConstruct
@ -1,300 +0,0 @@
|
|||||||
#Sconstruct
|
|
||||||
|
|
||||||
import os
|
|
||||||
import os.path
|
|
||||||
import string
|
|
||||||
import sys
|
|
||||||
from subprocess import call
|
|
||||||
|
|
||||||
def CheckBoost(context, version):
|
|
||||||
# Boost versions are in format major.minor.subminor
|
|
||||||
v_arr = version.split(".")
|
|
||||||
version_n = 0
|
|
||||||
if len(v_arr) > 0:
|
|
||||||
version_n += int(v_arr[0])*100000
|
|
||||||
if len(v_arr) > 1:
|
|
||||||
version_n += int(v_arr[1])*100
|
|
||||||
if len(v_arr) > 2:
|
|
||||||
version_n += int(v_arr[2])
|
|
||||||
|
|
||||||
context.Message('Checking for Boost version >= %s... ' % (version))
|
|
||||||
ret = context.TryRun("""
|
|
||||||
#include <boost/version.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
return BOOST_VERSION >= %d ? 0 : 1;
|
|
||||||
}
|
|
||||||
""" % version_n, '.cpp')[0]
|
|
||||||
context.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def CheckProtobuf(context, version):
|
|
||||||
# Protobuf versions are in format major.minor.subminor
|
|
||||||
v_arr = version.split(".")
|
|
||||||
version_n = 0
|
|
||||||
if len(v_arr) > 0:
|
|
||||||
version_n += int(v_arr[0])*1000000
|
|
||||||
if len(v_arr) > 1:
|
|
||||||
version_n += int(v_arr[1])*1000
|
|
||||||
if len(v_arr) > 2:
|
|
||||||
version_n += int(v_arr[2])
|
|
||||||
|
|
||||||
context.Message('Checking for Protobuffer version >= %s... ' % (version))
|
|
||||||
ret = context.TryRun("""
|
|
||||||
#include <google/protobuf/stubs/common.h>
|
|
||||||
int main() {
|
|
||||||
return (GOOGLE_PROTOBUF_VERSION >= %d) ? 0 : 1;
|
|
||||||
}
|
|
||||||
""" % version_n, '.cpp')[0]
|
|
||||||
context.Result(ret)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# Adding various options to the SConstruct
|
|
||||||
AddOption('--cxx', dest='cxx', type='string', nargs=1, action='store', metavar='STRING', help='C++ Compiler')
|
|
||||||
AddOption('--stxxlroot', dest='stxxlroot', type='string', nargs=1, action='store', metavar='STRING', help='root directory of STXXL')
|
|
||||||
AddOption('--verbosity', dest='verbosity', type='string', nargs=1, action='store', metavar='STRING', help='make Scons talking')
|
|
||||||
AddOption('--buildconfiguration', dest='buildconfiguration', type='string', nargs=1, action='store', metavar='STRING', help='debug or release')
|
|
||||||
AddOption('--all-flags', dest='allflags', type='string', nargs=0, action='store', metavar='STRING', help='turn off -march optimization in release mode')
|
|
||||||
AddOption('--with-tools', dest='withtools', type='string', nargs=0, action='store', metavar='STRING', help='build tools for data analysis')
|
|
||||||
AddOption('--no-march', dest='nomarch', type='string', nargs=0, action='store', metavar='STRING', help='turn off native optimizations')
|
|
||||||
|
|
||||||
env = Environment( ENV = {'PATH' : os.environ['PATH']} ,COMPILER = GetOption('cxx'))
|
|
||||||
env["CC"] = os.getenv("CC") or env["CC"]
|
|
||||||
env["CXX"] = os.getenv("CXX") or env["CXX"]
|
|
||||||
env["ENV"].update(x for x in os.environ.items() if x[0].startswith("CCC_"))
|
|
||||||
try:
|
|
||||||
env['ENV']['TERM'] = os.environ['TERM']
|
|
||||||
except KeyError:
|
|
||||||
env['ENV']['TERM'] = 'none'
|
|
||||||
|
|
||||||
conf = Configure(env, custom_tests = { 'CheckBoost' : CheckBoost, 'CheckProtobuf' : CheckProtobuf })
|
|
||||||
|
|
||||||
if GetOption('cxx') is None:
|
|
||||||
#default Compiler
|
|
||||||
if sys.platform == 'darwin': #Mac OS X
|
|
||||||
env['CXX'] = 'clang++'
|
|
||||||
print 'Using default C++ Compiler: ', env['CXX'].strip()
|
|
||||||
else:
|
|
||||||
env.Replace(CXX = GetOption('cxx'))
|
|
||||||
print 'Using user supplied C++ Compiler: ', env['CXX']
|
|
||||||
|
|
||||||
if GetOption('allflags') is not None:
|
|
||||||
env.Append(CXXFLAGS = ["-Wextra", "-Wall", "-Wnon-virtual-dtor", "-Wundef", "-Wno-long-long", "-Woverloaded-virtual", "-Wfloat-equal", "-Wredundant-decls"])
|
|
||||||
|
|
||||||
if "clang" in env["CXX"]:
|
|
||||||
print "Warning building with clang removes OpenMP parallelization"
|
|
||||||
if GetOption('allflags') is not None:
|
|
||||||
env.Append(CXXFLAGS = ["-W#warnings", "-Wc++0x-compat", "-Waddress-of-temporary", "-Wambiguous-member-template", "-Warray-bounds", "-Watomic-properties", "-Wbind-to-temporary-copy", "-Wbuiltin-macro-redefined", "-Wc++-compat", "-Wc++0x-extensions", "-Wcomments", "-Wconditional-uninitialized", "-Wconstant-logical-operand", "-Wdeclaration-after-statement", "-Wdeprecated", "-Wdeprecated-implementations", "-Wdeprecated-writable-strings", "-Wduplicate-method-arg", "-Wempty-body", "-Wendif-labels", "-Wenum-compare", "-Wformat=2", "-Wfour-char-constants", "-Wgnu", "-Wincomplete-implementation", "-Winvalid-noreturn", "-Winvalid-offsetof", "-Winvalid-token-paste", "-Wlocal-type-template-args", "-Wmethod-signatures", "-Wmicrosoft", "-Wmissing-declarations", "-Wnon-pod-varargs", "-Wnonfragile-abi2", "-Wnull-dereference", "-Wout-of-line-declaration", "-Woverlength-strings", "-Wpacked", "-Wpointer-arith", "-Wpointer-sign", "-Wprotocol", "-Wreadonly-setter-attrs", "-Wselector", "-Wshift-overflow", "-Wshift-sign-overflow", "-Wstrict-selector-match", "-Wsuper-class-method-mismatch", "-Wtautological-compare", "-Wtypedef-redefinition", "-Wundeclared-selector", "-Wunnamed-type-template-args", "-Wunused-exception-parameter", "-Wunused-member-function", "-Wused-but-marked-unused", "-Wvariadic-macros"])
|
|
||||||
else:
|
|
||||||
env.Append(CCFLAGS = ['-minline-all-stringops', '-fopenmp', '-Wall'])
|
|
||||||
env.Append(LINKFLAGS = '-fopenmp')
|
|
||||||
|
|
||||||
if GetOption('buildconfiguration') == 'debug':
|
|
||||||
env.Append(CCFLAGS = ['-Wall', '-g3', '-rdynamic'])
|
|
||||||
else:
|
|
||||||
env.Append(CCFLAGS = ['-O3', '-DNDEBUG'])
|
|
||||||
|
|
||||||
if sys.platform == 'darwin': #Mac OS X
|
|
||||||
#os x default installations
|
|
||||||
env.Append(CPPPATH = ['/usr/include/libxml2'] )
|
|
||||||
env.Append(CPPPATH = ['/usr/X11/include']) #comes with os x
|
|
||||||
# env.Append(LIBPATH = ['/usr/X11/lib']) #needed for libpng
|
|
||||||
|
|
||||||
#assume stxxl and boost are installed via homebrew. call brew binary to get folder locations
|
|
||||||
import subprocess
|
|
||||||
stxxl_prefix = subprocess.check_output(["brew", "--prefix", "libstxxl"]).strip()
|
|
||||||
env.Append(CPPPATH = [stxxl_prefix+"/include"] )
|
|
||||||
env.Append(LIBPATH = [stxxl_prefix+"/lib"] )
|
|
||||||
boost_prefix = subprocess.check_output(["brew", "--prefix", "boost"]).strip()
|
|
||||||
env.Append(CPPPATH = [boost_prefix+"/include"] )
|
|
||||||
env.Append(LIBPATH = [boost_prefix+"/lib"] )
|
|
||||||
if not conf.CheckLibWithHeader('lua', 'lua.h', 'C'):
|
|
||||||
print "lua library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
if not conf.CheckLibWithHeader('luabind', 'luabind/luabind.hpp', 'CXX'):
|
|
||||||
print "luabind library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
elif sys.platform.startswith("freebsd"):
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs protobuf')
|
|
||||||
env.Append(CPPPATH = ['/usr/local/include', '/usr/local/include/libxml2'])
|
|
||||||
env.Append(LIBPATH = ['/usr/local/lib'])
|
|
||||||
if GetOption('stxxlroot') is not None:
|
|
||||||
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
|
|
||||||
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
|
|
||||||
print 'STXXLROOT = ', GetOption('stxxlroot')
|
|
||||||
elif sys.platform == 'win32':
|
|
||||||
#SCons really wants to use Microsoft compiler
|
|
||||||
print "Compiling is not yet supported on Windows"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "Default platform"
|
|
||||||
if GetOption('stxxlroot') is not None:
|
|
||||||
env.Append(CPPPATH = GetOption('stxxlroot')+'/include')
|
|
||||||
env.Append(LIBPATH = GetOption('stxxlroot')+'/lib')
|
|
||||||
print 'STXXLROOT = ', GetOption('stxxlroot')
|
|
||||||
env.Append(CPPPATH = ['/usr/include', '/usr/include/include', '/usr/include/libxml2/'])
|
|
||||||
if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'CXX'):
|
|
||||||
print "pthread not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
if not conf.CheckLibWithHeader('luajit-5.1', 'luajit-2.0/lua.h', 'CXX'):
|
|
||||||
print "luajit library not found. Checking for interpreter"
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs lua5.1')
|
|
||||||
env.ParseConfig('pkg-config --cflags --libs luabind')
|
|
||||||
|
|
||||||
#Check if architecture optimizations shall be turned off
|
|
||||||
if GetOption('buildconfiguration') != 'debug' and sys.platform != 'darwin' and GetOption('nomarch') is None:
|
|
||||||
env.Append(CCFLAGS = ['-march=native'])
|
|
||||||
|
|
||||||
if not conf.CheckHeader('omp.h'):
|
|
||||||
if "clang" not in env["CXX"]:
|
|
||||||
print "OpenMP not found, Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('bz2', 'bzlib.h', 'CXX'):
|
|
||||||
print "bz2 library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if GetOption('withtools') is not None:
|
|
||||||
if not conf.CheckLibWithHeader('gdal', 'gdal/gdal.h', 'CXX'):
|
|
||||||
print "gdal library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('osmpbf', 'osmpbf/osmpbf.h', 'CXX'):
|
|
||||||
print "osmpbf library not found. Exiting"
|
|
||||||
print "Either install libosmpbf-dev (Ubuntu) or use https://github.com/scrosby/OSM-binary"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('protobuf', 'google/protobuf/descriptor.h', 'CXX'):
|
|
||||||
print "Google Protobuffer library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
#check for protobuf 2.3.0
|
|
||||||
if not (conf.CheckProtobuf('2.3.0')):
|
|
||||||
print 'libprotobuf version >= 2.3.0 needed'
|
|
||||||
Exit(-1);
|
|
||||||
if not (env.Detect('protoc')):
|
|
||||||
print 'protobuffer compiler not found'
|
|
||||||
Exit(-1);
|
|
||||||
if not conf.CheckLibWithHeader('stxxl', 'stxxl.h', 'CXX'):
|
|
||||||
print "stxxl library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('xml2', 'libxml/xmlreader.h', 'CXX'):
|
|
||||||
print "libxml2 library or header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckLibWithHeader('z', 'zlib.h', 'CXX'):
|
|
||||||
print "zlib library or header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
#Check BOOST installation
|
|
||||||
if not (conf.CheckBoost('1.44')):
|
|
||||||
print 'Boost version >= 1.44 needed'
|
|
||||||
Exit(-1);
|
|
||||||
if not conf.CheckLib('boost_system', language="C++"):
|
|
||||||
if not conf.CheckLib('boost_system-mt', language="C++"):
|
|
||||||
print "boost_system library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_system-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_system-mt')
|
|
||||||
if not conf.CheckLibWithHeader('boost_thread', 'boost/thread.hpp', 'CXX'):
|
|
||||||
if not conf.CheckLibWithHeader('boost_thread-mt', 'boost/thread.hpp', 'CXX'):
|
|
||||||
print "boost thread library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_thread-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_thread-mt')
|
|
||||||
if not conf.CheckLibWithHeader('boost_regex', 'boost/regex.hpp', 'CXX'):
|
|
||||||
if not conf.CheckLibWithHeader('boost_regex-mt', 'boost/regex.hpp', 'CXX'):
|
|
||||||
print "boost/regex.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost_regex -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_regex-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_regex-mt')
|
|
||||||
if not conf.CheckLib('boost_filesystem', language="C++"):
|
|
||||||
if not conf.CheckLib('boost_filesystem-mt', language="C++"):
|
|
||||||
print "boost_filesystem library not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
else:
|
|
||||||
print "using boost -mt"
|
|
||||||
env.Append(CCFLAGS = ' -lboost_filesystem-mt')
|
|
||||||
env.Append(LINKFLAGS = ' -lboost_filesystem-mt')
|
|
||||||
if not conf.CheckCXXHeader('boost/archive/iterators/base64_from_binary.hpp'):
|
|
||||||
print "boost/archive/iterators/base64_from_binary.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/archive/iterators/binary_from_base64.hpp'):
|
|
||||||
print "boost/archive/iterators/binary_from_base64.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/archive/iterators/transform_width.hpp'):
|
|
||||||
print "boost/archive/iterators/transform_width.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/bind.hpp'):
|
|
||||||
print "boost/bind.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/circular_buffer.hpp'):
|
|
||||||
print "boost/circular_buffer.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/enable_shared_from_this.hpp'):
|
|
||||||
print "boost/bind.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/foreach.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/lexical_cast.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/logic/tribool.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/math/tr1.hpp'):
|
|
||||||
print "boost/foreach.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/noncopyable.hpp'):
|
|
||||||
print "boost/noncopyable.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/property_tree/ptree.hpp'):
|
|
||||||
print "boost/property_tree/ptree.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/property_tree/ini_parser.hpp'):
|
|
||||||
print "boost/property_tree/ini_parser.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/shared_ptr.hpp'):
|
|
||||||
print "boost/shared_ptr.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/mutex.hpp'):
|
|
||||||
print "boost/shared_ptr.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
|
|
||||||
print "boost/thread/thread.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/condition.hpp'):
|
|
||||||
print "boost/thread/condition.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread/thread.hpp'):
|
|
||||||
print "boost/thread/thread.hpp not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/thread.hpp'):
|
|
||||||
print "boost thread header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/tuple/tuple.hpp'):
|
|
||||||
print "boost thread header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
if not conf.CheckCXXHeader('boost/unordered_map.hpp'):
|
|
||||||
print "boost thread header not found. Exiting"
|
|
||||||
Exit(-1)
|
|
||||||
|
|
||||||
#checks for intels thread building blocks library
|
|
||||||
#if not conf.CheckLibWithHeader('tbb', 'tbb/tbb.h', 'CXX'):
|
|
||||||
# print "Intel TBB library not found. Exiting"
|
|
||||||
# Exit(-1)
|
|
||||||
#if not conf.CheckCXXHeader('tbb/task_scheduler_init.h'):
|
|
||||||
# print "tbb/task_scheduler_init.h not found. Exiting"
|
|
||||||
# Exit(-1)
|
|
||||||
|
|
||||||
env.Program(target = 'osrm-extract', source = ["extractor.cpp", Glob('Util/*.cpp'), Glob('Extractor/*.cpp')])
|
|
||||||
env.Program(target = 'osrm-prepare', source = ["createHierarchy.cpp", Glob('Contractor/*.cpp'), Glob('Util/SRTMLookup/*.cpp'), Glob('Algorithms/*.cpp')])
|
|
||||||
env.Program(target = 'osrm-routed', source = ["routed.cpp", 'Descriptors/DescriptionFactory.cpp', Glob('ThirdParty/*.cc'), Glob('Server/DataStructures/*.cpp')], CCFLAGS = env['CCFLAGS'] + ['-DROUTED'])
|
|
||||||
if GetOption('withtools') is not None:
|
|
||||||
env.Program(target = 'Tools/osrm-component', source = ["Tools/componentAnalysis.cpp"])
|
|
||||||
env = conf.Finish()
|
|
||||||
|
|
@ -21,8 +21,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef BASIC_DATASTRUCTURES_H
|
#ifndef BASIC_DATASTRUCTURES_H
|
||||||
#define BASIC_DATASTRUCTURES_H
|
#define BASIC_DATASTRUCTURES_H
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
@ -143,7 +143,11 @@ Reply Reply::stockReply(Reply::status_type status) {
|
|||||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||||
rep.headers[0].value = "*";
|
rep.headers[0].value = "*";
|
||||||
rep.headers[1].name = "Content-Length";
|
rep.headers[1].name = "Content-Length";
|
||||||
rep.headers[1].value = boost::lexical_cast<std::string>(rep.content.size());
|
|
||||||
|
std::string s;
|
||||||
|
intToString(rep.content.size(), s);
|
||||||
|
|
||||||
|
rep.headers[1].value = s;
|
||||||
rep.headers[2].name = "Content-Type";
|
rep.headers[2].name = "Content-Type";
|
||||||
rep.headers[2].value = "text/html";
|
rep.headers[2].value = "text/html";
|
||||||
return rep;
|
return rep;
|
||||||
|
@ -22,14 +22,27 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "QueryObjectsStorage.h"
|
#include "QueryObjectsStorage.h"
|
||||||
#include "../../Util/GraphLoader.h"
|
#include "../../Util/GraphLoader.h"
|
||||||
|
|
||||||
QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath) {
|
QueryObjectsStorage::QueryObjectsStorage(
|
||||||
|
std::string hsgrPath,
|
||||||
|
std::string ramIndexPath,
|
||||||
|
std::string fileIndexPath,
|
||||||
|
std::string nodesPath,
|
||||||
|
std::string edgesPath,
|
||||||
|
std::string namesPath,
|
||||||
|
std::string timestampPath
|
||||||
|
) {
|
||||||
INFO("loading graph data");
|
INFO("loading graph data");
|
||||||
std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary);
|
std::ifstream hsgrInStream(hsgrPath.c_str(), std::ios::binary);
|
||||||
if(!hsgrInStream) { ERR(hsgrPath << " not found"); }
|
if(!hsgrInStream) { ERR(hsgrPath << " not found"); }
|
||||||
//Deserialize road network graph
|
//Deserialize road network graph
|
||||||
std::vector< QueryGraph::_StrNode> nodeList;
|
std::vector< QueryGraph::_StrNode> nodeList;
|
||||||
std::vector< QueryGraph::_StrEdge> edgeList;
|
std::vector< QueryGraph::_StrEdge> edgeList;
|
||||||
const int n = readHSGRFromStream(hsgrInStream, nodeList, edgeList, &checkSum);
|
const int n = readHSGRFromStream(
|
||||||
|
hsgrInStream,
|
||||||
|
nodeList,
|
||||||
|
edgeList,
|
||||||
|
&checkSum
|
||||||
|
);
|
||||||
|
|
||||||
INFO("Data checksum is " << checkSum);
|
INFO("Data checksum is " << checkSum);
|
||||||
graph = new QueryGraph(nodeList, edgeList);
|
graph = new QueryGraph(nodeList, edgeList);
|
||||||
@ -39,7 +52,7 @@ QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIn
|
|||||||
if(timestampPath.length()) {
|
if(timestampPath.length()) {
|
||||||
INFO("Loading Timestamp");
|
INFO("Loading Timestamp");
|
||||||
std::ifstream timestampInStream(timestampPath.c_str());
|
std::ifstream timestampInStream(timestampPath.c_str());
|
||||||
if(!timestampInStream) { ERR(timestampPath << " not found"); }
|
if(!timestampInStream) { WARN(timestampPath << " not found"); }
|
||||||
|
|
||||||
getline(timestampInStream, timestamp);
|
getline(timestampInStream, timestamp);
|
||||||
timestampInStream.close();
|
timestampInStream.close();
|
||||||
|
@ -25,7 +25,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <cctype> // std::tolower
|
#include <cctype> // std::tolower
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
#include "APIGrammar.h"
|
#include "APIGrammar.h"
|
||||||
@ -52,19 +51,20 @@ public:
|
|||||||
|
|
||||||
void handle_request(const Request& req, Reply& rep){
|
void handle_request(const Request& req, Reply& rep){
|
||||||
//parse command
|
//parse command
|
||||||
std::string request(req.uri);
|
|
||||||
|
|
||||||
{ //This block logs the current request to std out. should be moved to a logging component
|
|
||||||
time_t ltime;
|
|
||||||
struct tm *Tm;
|
|
||||||
|
|
||||||
ltime=time(NULL);
|
|
||||||
Tm=localtime(<ime);
|
|
||||||
|
|
||||||
INFO((Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " <<
|
|
||||||
req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri );
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
|
std::string request(req.uri);
|
||||||
|
|
||||||
|
{ //This block logs the current request to std out. should be moved to a logging component
|
||||||
|
time_t ltime;
|
||||||
|
struct tm *Tm;
|
||||||
|
|
||||||
|
ltime=time(NULL);
|
||||||
|
Tm=localtime(<ime);
|
||||||
|
|
||||||
|
INFO((Tm->tm_mday < 10 ? "0" : "" ) << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" ) << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " <<
|
||||||
|
req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri );
|
||||||
|
}
|
||||||
|
|
||||||
RouteParameters routeParameters;
|
RouteParameters routeParameters;
|
||||||
APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
|
APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters);
|
||||||
|
|
||||||
|
@ -21,6 +21,15 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#ifndef GRAPHLOADER_H
|
#ifndef GRAPHLOADER_H
|
||||||
#define GRAPHLOADER_H
|
#define GRAPHLOADER_H
|
||||||
|
|
||||||
|
#include "../DataStructures/ImportNode.h"
|
||||||
|
#include "../DataStructures/ImportEdge.h"
|
||||||
|
#include "../DataStructures/NodeCoords.h"
|
||||||
|
#include "../DataStructures/Restriction.h"
|
||||||
|
#include "../typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@ -30,19 +39,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
|
|
||||||
#include "../DataStructures/ImportNode.h"
|
|
||||||
#include "../DataStructures/ImportEdge.h"
|
|
||||||
#include "../DataStructures/NodeCoords.h"
|
|
||||||
#include "../DataStructures/Restriction.h"
|
|
||||||
#include "../typedefs.h"
|
|
||||||
|
|
||||||
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
|
typedef boost::unordered_map<NodeID, NodeID> ExternalNodeMap;
|
||||||
|
|
||||||
template<class EdgeT>
|
template<class EdgeT>
|
||||||
struct _ExcessRemover {
|
struct _ExcessRemover {
|
||||||
inline bool operator()( EdgeT & edge ) const {
|
inline bool operator()( const EdgeT & edge ) const {
|
||||||
return edge.source() == UINT_MAX;
|
return edge.source() == UINT_MAX;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -116,9 +117,9 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
in.read((char*)&isAccessRestricted, sizeof(bool));
|
in.read((char*)&isAccessRestricted, sizeof(bool));
|
||||||
in.read((char*)&isContraFlow, sizeof(bool));
|
in.read((char*)&isContraFlow, sizeof(bool));
|
||||||
|
|
||||||
GUARANTEE(length > 0, "loaded null length edge" );
|
BOOST_ASSERT_MSG(length > 0, "loaded null length edge" );
|
||||||
GUARANTEE(weight > 0, "loaded null weight");
|
BOOST_ASSERT_MSG(weight > 0, "loaded null weight");
|
||||||
GUARANTEE(0<=dir && dir<=2, "loaded bogus direction");
|
BOOST_ASSERT_MSG(0<=dir && dir<=2, "loaded bogus direction");
|
||||||
|
|
||||||
bool forward = true;
|
bool forward = true;
|
||||||
bool backward = true;
|
bool backward = true;
|
||||||
@ -144,7 +145,9 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
target = intNodeID->second;
|
target = intNodeID->second;
|
||||||
GUARANTEE(source != UINT_MAX && target != UINT_MAX, "nonexisting source or target");
|
BOOST_ASSERT_MSG(source != UINT_MAX && target != UINT_MAX,
|
||||||
|
"nonexisting source or target"
|
||||||
|
);
|
||||||
|
|
||||||
if(source > target) {
|
if(source > target) {
|
||||||
std::swap(source, target);
|
std::swap(source, target);
|
||||||
@ -185,9 +188,9 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<ImportEdge>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
|
typename std::vector<EdgeT>::iterator newEnd = std::remove_if(edgeList.begin(), edgeList.end(), _ExcessRemover<EdgeT>());
|
||||||
ext2IntNodeMap.clear();
|
ext2IntNodeMap.clear();
|
||||||
std::vector<ImportEdge>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edgeList.begin(), newEnd).swap(edgeList); //remove excess candidates.
|
||||||
INFO("Graph loaded ok and has " << edgeList.size() << " edges");
|
INFO("Graph loaded ok and has " << edgeList.size() << " edges");
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@ -299,7 +302,7 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector<EdgeT>& edgeList, s
|
|||||||
edgeList.push_back(inputEdge);
|
edgeList.push_back(inputEdge);
|
||||||
}
|
}
|
||||||
ext2IntNodeMap.clear();
|
ext2IntNodeMap.clear();
|
||||||
std::vector<ImportEdge>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
|
std::vector<EdgeT>(edgeList.begin(), edgeList.end()).swap(edgeList); //remove excess candidates.
|
||||||
std::cout << "ok" << std::endl;
|
std::cout << "ok" << std::endl;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef LUAUTIL_H_
|
#ifndef LUAUTIL_H_
|
||||||
#define LUAUTIL_H_
|
#define LUAUTIL_H_
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <boost/filesystem/convenience.hpp>
|
||||||
|
#include <luabind/luabind.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/filesystem/convenience.hpp>
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void LUA_print(T number) {
|
void LUA_print(T number) {
|
||||||
|
75
cmake/FindLuabind.cmake
Normal file
75
cmake/FindLuabind.cmake
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Locate Luabind library
|
||||||
|
# This module defines
|
||||||
|
# LUABIND_FOUND, if false, do not try to link to Luabind
|
||||||
|
# LUABIND_LIBRARIES
|
||||||
|
# LUABIND_INCLUDE_DIR, where to find luabind.hpp
|
||||||
|
#
|
||||||
|
# Note that the expected include convention is
|
||||||
|
# #include <luabind/luabind.hpp>
|
||||||
|
# and not
|
||||||
|
# #include <luabind.hpp>
|
||||||
|
|
||||||
|
IF( NOT LUABIND_FIND_QUIETLY )
|
||||||
|
MESSAGE(STATUS "Looking for Luabind...")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_PATH(LUABIND_INCLUDE_DIR luabind.hpp
|
||||||
|
HINTS
|
||||||
|
$ENV{LUABIND_DIR}
|
||||||
|
PATH_SUFFIXES luabind include/luabind include
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(LUABIND_LIBRARY
|
||||||
|
NAMES luabind
|
||||||
|
HINTS
|
||||||
|
$ENV{LUABIND_DIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(LUABIND_LIBRARY_DBG
|
||||||
|
NAMES luabindd
|
||||||
|
HINTS
|
||||||
|
$ENV{LUABIND_DIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
IF(LUABIND_LIBRARY)
|
||||||
|
SET( LUABIND_LIBRARIES "${LUABIND_LIBRARY}" CACHE STRING "Luabind Libraries")
|
||||||
|
ENDIF(LUABIND_LIBRARY)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set LUABIND_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Luabind DEFAULT_MSG LUABIND_LIBRARIES LUABIND_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF( NOT LUABIND_FIND_QUIETLY )
|
||||||
|
IF( LUABIND_FOUND )
|
||||||
|
MESSAGE(STATUS "Found Luabind: ${LUABIND_LIBRARY}" )
|
||||||
|
ENDIF()
|
||||||
|
IF( LUABIND_LIBRARY_DBG )
|
||||||
|
MESSAGE(STATUS "Luabind debug library availible: ${LUABIND_LIBRARY_DBG}")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(LUABIND_INCLUDE_DIR LUABIND_LIBRARIES LUABIND_LIBRARY LUABIND_LIBRARY_DBG)
|
54
cmake/FindOSMPBF.cmake
Normal file
54
cmake/FindOSMPBF.cmake
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Locate OSMPBF library
|
||||||
|
# This module defines
|
||||||
|
# OSMPBF_FOUND, if false, do not try to link to OSMPBF
|
||||||
|
# OSMPBF_LIBRARIES
|
||||||
|
# OSMPBF_INCLUDE_DIR, where to find OSMPBF.hpp
|
||||||
|
#
|
||||||
|
# Note that the expected include convention is
|
||||||
|
# #include <osmpbf/osmpbf.h>
|
||||||
|
# and not
|
||||||
|
# #include <osmpbf.h>
|
||||||
|
|
||||||
|
IF( NOT OSMPBF_FIND_QUIETLY )
|
||||||
|
MESSAGE(STATUS "Looking for OSMPBF...")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_PATH(OSMPBF_INCLUDE_DIR osmpbf.h
|
||||||
|
HINTS
|
||||||
|
$ENV{OSMPBF_DIR}
|
||||||
|
PATH_SUFFIXES OSMPBF include/osmpbf include
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(OSMPBF_LIBRARY
|
||||||
|
NAMES osmpbf
|
||||||
|
HINTS
|
||||||
|
$ENV{OSMPBF_DIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set OSMPBF_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OSMPBF DEFAULT_MSG OSMPBF_LIBRARY OSMPBF_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF( NOT OSMPBF_FIND_QUIETLY )
|
||||||
|
IF( OSMPBF_FOUND )
|
||||||
|
MESSAGE(STATUS "Found OSMPBF: ${OSMPBF_LIBRARY}" )
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
#MARK_AS_ADVANCED(OSMPBF_INCLUDE_DIR OSMPBF_LIBRARIES OSMPBF_LIBRARY OSMPBF_LIBRARY_DBG)
|
51
cmake/FindSTXXL.cmake
Normal file
51
cmake/FindSTXXL.cmake
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Locate STXXL library
|
||||||
|
# This module defines
|
||||||
|
# STXXL_FOUND, if false, do not try to link to libstxxl
|
||||||
|
# STXXL_LIBRARY
|
||||||
|
# STXXL_INCLUDE_DIR, where to find stxxl.h
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
IF( NOT STXXL_FIND_QUIETLY )
|
||||||
|
MESSAGE(STATUS "Looking for STXXL...")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
FIND_PATH(STXXL_INCLUDE_DIR stxxl.h
|
||||||
|
HINTS
|
||||||
|
$ENV{STXXL_DIR}
|
||||||
|
PATH_SUFFIXES stxxl include/stxxl/stxxl include/stxxl include
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
FIND_LIBRARY(STXXL_LIBRARY
|
||||||
|
NAMES stxxl
|
||||||
|
HINTS
|
||||||
|
$ENV{STXXL_DIR}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
PATHS
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/usr/local
|
||||||
|
/usr
|
||||||
|
/opt/local
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
INCLUDE(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set STXXL_FOUND to TRUE if
|
||||||
|
# all listed variables are TRUE
|
||||||
|
FIND_PACKAGE_HANDLE_STANDARD_ARGS(STXXL DEFAULT_MSG STXXL_LIBRARY STXXL_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF( NOT STXXL_FIND_QUIETLY )
|
||||||
|
IF( STXXL_FOUND )
|
||||||
|
MESSAGE(STATUS "Found STXXL: ${STXXL_LIBRARY}" )
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
|
MARK_AS_ADVANCED(STXXL_INCLUDE_DIR STXXL_LIBRARY)
|
123
cmake/GetGitRevisionDescription.cmake
Normal file
123
cmake/GetGitRevisionDescription.cmake
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# - Returns a version string from Git
|
||||||
|
#
|
||||||
|
# These functions force a re-configure on each git commit so that you can
|
||||||
|
# trust the values of the variables in your build system.
|
||||||
|
#
|
||||||
|
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the refspec and sha hash of the current head revision
|
||||||
|
#
|
||||||
|
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the source tree, and adjusting
|
||||||
|
# the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe --exact-match on the source tree,
|
||||||
|
# and adjusting the output so that it tests false if there was no exact
|
||||||
|
# matching tag.
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright Iowa State University 2009-2010.
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
if(__get_git_revision_description)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(__get_git_revision_description YES)
|
||||||
|
|
||||||
|
# We must run the following at "include" time, not at function call time,
|
||||||
|
# to find the path to this module rather than the path to a calling list file
|
||||||
|
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
|
function(get_git_head_revision _refspecvar _hashvar)
|
||||||
|
set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
|
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||||
|
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||||
|
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||||
|
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||||
|
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||||
|
# We have reached the root directory, we are not in git
|
||||||
|
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||||
|
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||||
|
endwhile()
|
||||||
|
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||||
|
if(NOT EXISTS "${GIT_DATA}")
|
||||||
|
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||||
|
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||||
|
|
||||||
|
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||||
|
"${GIT_DATA}/grabRef.cmake"
|
||||||
|
@ONLY)
|
||||||
|
include("${GIT_DATA}/grabRef.cmake")
|
||||||
|
|
||||||
|
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||||
|
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO sanitize
|
||||||
|
#if((${ARGN}" MATCHES "&&") OR
|
||||||
|
# (ARGN MATCHES "||") OR
|
||||||
|
# (ARGN MATCHES "\\;"))
|
||||||
|
# message("Please report the following error to the project!")
|
||||||
|
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||||
|
|
||||||
|
execute_process(COMMAND
|
||||||
|
"${GIT_EXECUTABLE}"
|
||||||
|
describe
|
||||||
|
${hash}
|
||||||
|
${ARGN}
|
||||||
|
WORKING_DIRECTORY
|
||||||
|
"${CMAKE_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE
|
||||||
|
res
|
||||||
|
OUTPUT_VARIABLE
|
||||||
|
out
|
||||||
|
ERROR_QUIET
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var} "${out}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_get_exact_tag _var)
|
||||||
|
git_describe(out --exact-match ${ARGN})
|
||||||
|
set(${_var} "${out}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
@ -18,15 +18,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern "C" {
|
#include "Algorithms/IteratorBasedCRC32.h"
|
||||||
#include <lua.h>
|
#include "Contractor/Contractor.h"
|
||||||
#include <lauxlib.h>
|
#include "Contractor/EdgeBasedGraphFactory.h"
|
||||||
#include <lualib.h>
|
#include "DataStructures/BinaryHeap.h"
|
||||||
}
|
#include "DataStructures/DeallocatingVector.h"
|
||||||
#include <luabind/luabind.hpp>
|
#include "DataStructures/QueryEdge.h"
|
||||||
|
#include "DataStructures/StaticGraph.h"
|
||||||
|
#include "DataStructures/StaticRTree.h"
|
||||||
|
#include "Util/BaseConfiguration.h"
|
||||||
|
#include "Util/GraphLoader.h"
|
||||||
|
#include "Util/InputFileUtil.h"
|
||||||
|
#include "Util/LuaUtil.h"
|
||||||
|
#include "Util/OpenMPWrapper.h"
|
||||||
|
#include "Util/StringUtil.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include <luabind/luabind.hpp>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -34,21 +45,6 @@ extern "C" {
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Algorithms/IteratorBasedCRC32.h"
|
|
||||||
#include "Util/OpenMPWrapper.h"
|
|
||||||
#include "typedefs.h"
|
|
||||||
#include "Contractor/Contractor.h"
|
|
||||||
#include "Contractor/EdgeBasedGraphFactory.h"
|
|
||||||
#include "DataStructures/BinaryHeap.h"
|
|
||||||
#include "DataStructures/DeallocatingVector.h"
|
|
||||||
#include "DataStructures/NNGrid.h"
|
|
||||||
#include "DataStructures/QueryEdge.h"
|
|
||||||
#include "Util/BaseConfiguration.h"
|
|
||||||
#include "Util/GraphLoader.h"
|
|
||||||
#include "Util/InputFileUtil.h"
|
|
||||||
#include "Util/LuaUtil.h"
|
|
||||||
#include "Util/StringUtil.h"
|
|
||||||
|
|
||||||
typedef QueryEdge::EdgeData EdgeData;
|
typedef QueryEdge::EdgeData EdgeData;
|
||||||
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
||||||
typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
|
typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
|
||||||
@ -61,212 +57,220 @@ std::vector<NodeID> trafficLightNodes;
|
|||||||
std::vector<ImportEdge> edgeList;
|
std::vector<ImportEdge> edgeList;
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main (int argc, char *argv[]) {
|
||||||
if(argc < 3) {
|
try {
|
||||||
ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions> [<profile>]");
|
if(argc < 3) {
|
||||||
}
|
ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions> [<profile>]");
|
||||||
|
|
||||||
double startupTime = get_timestamp();
|
|
||||||
unsigned numberOfThreads = omp_get_num_procs();
|
|
||||||
if(testDataFile("contractor.ini")) {
|
|
||||||
ContractorConfiguration contractorConfig("contractor.ini");
|
|
||||||
unsigned rawNumber = stringToInt(contractorConfig.GetParameter("Threads"));
|
|
||||||
if(rawNumber != 0 && rawNumber <= numberOfThreads)
|
|
||||||
numberOfThreads = rawNumber;
|
|
||||||
}
|
|
||||||
omp_set_num_threads(numberOfThreads);
|
|
||||||
|
|
||||||
INFO("Using restrictions from file: " << argv[2]);
|
|
||||||
std::ifstream restrictionsInstream(argv[2], std::ios::binary);
|
|
||||||
if(!restrictionsInstream.good()) {
|
|
||||||
ERR("Could not access <osrm-restrictions> files");
|
|
||||||
}
|
|
||||||
_Restriction restriction;
|
|
||||||
unsigned usableRestrictionsCounter(0);
|
|
||||||
restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
|
||||||
inputRestrictions.resize(usableRestrictionsCounter);
|
|
||||||
restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
|
|
||||||
restrictionsInstream.close();
|
|
||||||
|
|
||||||
std::ifstream in;
|
|
||||||
in.open (argv[1], std::ifstream::in | std::ifstream::binary);
|
|
||||||
if (!in.is_open()) {
|
|
||||||
ERR("Cannot open " << argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string nodeOut(argv[1]); nodeOut += ".nodes";
|
|
||||||
std::string edgeOut(argv[1]); edgeOut += ".edges";
|
|
||||||
std::string graphOut(argv[1]); graphOut += ".hsgr";
|
|
||||||
std::string ramIndexOut(argv[1]); ramIndexOut += ".ramIndex";
|
|
||||||
std::string fileIndexOut(argv[1]); fileIndexOut += ".fileIndex";
|
|
||||||
|
|
||||||
/*** Setup Scripting Environment ***/
|
|
||||||
if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) {
|
|
||||||
ERR("Need profile.lua to apply traffic signal penalty");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new lua state
|
|
||||||
lua_State *myLuaState = luaL_newstate();
|
|
||||||
|
|
||||||
// Connect LuaBind to this lua state
|
|
||||||
luabind::open(myLuaState);
|
|
||||||
|
|
||||||
//open utility libraries string library;
|
|
||||||
luaL_openlibs(myLuaState);
|
|
||||||
|
|
||||||
//adjust lua load path
|
|
||||||
luaAddScriptFolderToLoadPath( myLuaState, (argc > 3 ? argv[3] : "profile.lua") );
|
|
||||||
|
|
||||||
// Now call our function in a lua script
|
|
||||||
INFO("Parsing speedprofile from " << (argc > 3 ? argv[3] : "profile.lua") );
|
|
||||||
if(0 != luaL_dofile(myLuaState, (argc > 3 ? argv[3] : "profile.lua") )) {
|
|
||||||
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeBasedGraphFactory::SpeedProfileProperties speedProfile;
|
|
||||||
|
|
||||||
if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) {
|
|
||||||
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
|
||||||
}
|
|
||||||
speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1);
|
|
||||||
|
|
||||||
if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) {
|
|
||||||
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
|
||||||
}
|
|
||||||
speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1);
|
|
||||||
|
|
||||||
speedProfile.has_turn_penalty_function = lua_function_exists( myLuaState, "turn_function" );
|
|
||||||
|
|
||||||
std::vector<ImportEdge> edgeList;
|
|
||||||
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
|
||||||
in.close();
|
|
||||||
INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
|
|
||||||
if(0 == edgeList.size())
|
|
||||||
ERR("The input data is broken. It is impossible to do any turns in this graph");
|
|
||||||
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Building an edge-expanded graph from node-based input an turn restrictions
|
|
||||||
*/
|
|
||||||
|
|
||||||
INFO("Generating edge-expanded graph representation");
|
|
||||||
EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile);
|
|
||||||
std::vector<ImportEdge>().swap(edgeList);
|
|
||||||
edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState);
|
|
||||||
std::vector<_Restriction>().swap(inputRestrictions);
|
|
||||||
std::vector<NodeID>().swap(bollardNodes);
|
|
||||||
std::vector<NodeID>().swap(trafficLightNodes);
|
|
||||||
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
|
|
||||||
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
|
|
||||||
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
|
|
||||||
DeallocatingVector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
|
|
||||||
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
|
|
||||||
delete edgeBasedGraphFactory;
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Writing info on original (node-based) nodes
|
|
||||||
*/
|
|
||||||
|
|
||||||
INFO("writing node map ...");
|
|
||||||
std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
|
|
||||||
mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
|
|
||||||
mapOutFile.close();
|
|
||||||
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
|
|
||||||
|
|
||||||
double expansionHasFinishedTime = get_timestamp() - startupTime;
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Building grid-like nearest-neighbor data structure
|
|
||||||
*/
|
|
||||||
|
|
||||||
INFO("building grid ...");
|
|
||||||
WritableGrid * writeableGrid = new WritableGrid();
|
|
||||||
writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut.c_str(), fileIndexOut.c_str());
|
|
||||||
delete writeableGrid;
|
|
||||||
IteratorbasedCRC32<DeallocatingVector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
|
|
||||||
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
|
|
||||||
nodeBasedEdgeList.clear();
|
|
||||||
INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList);
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Contracting the edge-expanded graph
|
|
||||||
*/
|
|
||||||
|
|
||||||
INFO("initializing contractor");
|
|
||||||
Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList );
|
|
||||||
double contractionStartedTimestamp(get_timestamp());
|
|
||||||
contractor->Run();
|
|
||||||
INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");
|
|
||||||
|
|
||||||
DeallocatingVector< QueryEdge > contractedEdgeList;
|
|
||||||
contractor->GetEdges( contractedEdgeList );
|
|
||||||
delete contractor;
|
|
||||||
|
|
||||||
/***
|
|
||||||
* Sorting contracted edges in a way that the static query graph can read some in in-place.
|
|
||||||
*/
|
|
||||||
|
|
||||||
INFO("Building Node Array");
|
|
||||||
std::sort(contractedEdgeList.begin(), contractedEdgeList.end());
|
|
||||||
unsigned numberOfNodes = 0;
|
|
||||||
unsigned numberOfEdges = contractedEdgeList.size();
|
|
||||||
INFO("Serializing compacted graph");
|
|
||||||
std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary);
|
|
||||||
|
|
||||||
BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) {
|
|
||||||
if(edge.source > numberOfNodes) {
|
|
||||||
numberOfNodes = edge.source;
|
|
||||||
}
|
}
|
||||||
if(edge.target > numberOfNodes) {
|
|
||||||
numberOfNodes = edge.target;
|
double startupTime = get_timestamp();
|
||||||
|
unsigned numberOfThreads = omp_get_num_procs();
|
||||||
|
if(testDataFile("contractor.ini")) {
|
||||||
|
ContractorConfiguration contractorConfig("contractor.ini");
|
||||||
|
unsigned rawNumber = stringToInt(contractorConfig.GetParameter("Threads"));
|
||||||
|
if(rawNumber != 0 && rawNumber <= numberOfThreads)
|
||||||
|
numberOfThreads = rawNumber;
|
||||||
}
|
}
|
||||||
}
|
omp_set_num_threads(numberOfThreads);
|
||||||
numberOfNodes+=1;
|
|
||||||
|
|
||||||
std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
|
INFO("Using restrictions from file: " << argv[2]);
|
||||||
_nodes.resize( numberOfNodes + 1 );
|
std::ifstream restrictionsInstream(argv[2], std::ios::binary);
|
||||||
|
if(!restrictionsInstream.good()) {
|
||||||
|
ERR("Could not access <osrm-restrictions> files");
|
||||||
|
}
|
||||||
|
_Restriction restriction;
|
||||||
|
unsigned usableRestrictionsCounter(0);
|
||||||
|
restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
||||||
|
inputRestrictions.resize(usableRestrictionsCounter);
|
||||||
|
restrictionsInstream.read((char *)&(inputRestrictions[0]), usableRestrictionsCounter*sizeof(_Restriction));
|
||||||
|
restrictionsInstream.close();
|
||||||
|
|
||||||
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
std::ifstream in;
|
||||||
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
in.open (argv[1], std::ifstream::in | std::ifstream::binary);
|
||||||
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
|
if (!in.is_open()) {
|
||||||
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
|
ERR("Cannot open " << argv[1]);
|
||||||
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
|
}
|
||||||
++edge;
|
|
||||||
_nodes[node].firstEdge = position; //=edge
|
std::string nodeOut(argv[1]); nodeOut += ".nodes";
|
||||||
position += edge - lastEdge; //remove
|
std::string edgeOut(argv[1]); edgeOut += ".edges";
|
||||||
}
|
std::string graphOut(argv[1]); graphOut += ".hsgr";
|
||||||
++numberOfNodes;
|
std::string rtree_nodes_path(argv[1]); rtree_nodes_path += ".ramIndex";
|
||||||
//Serialize numberOfNodes, nodes
|
std::string rtree_leafs_path(argv[1]); rtree_leafs_path += ".fileIndex";
|
||||||
edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
|
|
||||||
edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned));
|
/*** Setup Scripting Environment ***/
|
||||||
edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
|
if(!testDataFile( (argc > 3 ? argv[3] : "profile.lua") )) {
|
||||||
//Serialize number of Edges
|
ERR("Need profile.lua to apply traffic signal penalty");
|
||||||
edgeOutFile.write((char*) &position, sizeof(unsigned));
|
}
|
||||||
--numberOfNodes;
|
|
||||||
edge = 0;
|
// Create a new lua state
|
||||||
int usedEdgeCounter = 0;
|
lua_State *myLuaState = luaL_newstate();
|
||||||
StaticGraph<EdgeData>::_StrEdge currentEdge;
|
|
||||||
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
|
// Connect LuaBind to this lua state
|
||||||
for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
|
luabind::open(myLuaState);
|
||||||
assert(node != contractedEdgeList[edge].target);
|
|
||||||
currentEdge.target = contractedEdgeList[edge].target;
|
//open utility libraries string library;
|
||||||
currentEdge.data = contractedEdgeList[edge].data;
|
luaL_openlibs(myLuaState);
|
||||||
if(currentEdge.data.distance <= 0) {
|
|
||||||
INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance);
|
//adjust lua load path
|
||||||
ERR("Failed at edges of node " << node << " of " << numberOfNodes);
|
luaAddScriptFolderToLoadPath( myLuaState, (argc > 3 ? argv[3] : "profile.lua") );
|
||||||
|
|
||||||
|
// Now call our function in a lua script
|
||||||
|
INFO("Parsing speedprofile from " << (argc > 3 ? argv[3] : "profile.lua") );
|
||||||
|
if(0 != luaL_dofile(myLuaState, (argc > 3 ? argv[3] : "profile.lua") )) {
|
||||||
|
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
||||||
|
}
|
||||||
|
|
||||||
|
EdgeBasedGraphFactory::SpeedProfileProperties speedProfile;
|
||||||
|
|
||||||
|
if(0 != luaL_dostring( myLuaState, "return traffic_signal_penalty\n")) {
|
||||||
|
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
||||||
|
}
|
||||||
|
speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1);
|
||||||
|
|
||||||
|
if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) {
|
||||||
|
ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
|
||||||
|
}
|
||||||
|
speedProfile.uTurnPenalty = 10*lua_tointeger(myLuaState, -1);
|
||||||
|
|
||||||
|
speedProfile.has_turn_penalty_function = lua_function_exists( myLuaState, "turn_function" );
|
||||||
|
|
||||||
|
std::vector<ImportEdge> edgeList;
|
||||||
|
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
||||||
|
in.close();
|
||||||
|
INFO(inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
|
||||||
|
if(0 == edgeList.size())
|
||||||
|
ERR("The input data is broken. It is impossible to do any turns in this graph");
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Building an edge-expanded graph from node-based input an turn restrictions
|
||||||
|
*/
|
||||||
|
|
||||||
|
INFO("Generating edge-expanded graph representation");
|
||||||
|
EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile);
|
||||||
|
std::vector<ImportEdge>().swap(edgeList);
|
||||||
|
edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState);
|
||||||
|
std::vector<_Restriction>().swap(inputRestrictions);
|
||||||
|
std::vector<NodeID>().swap(bollardNodes);
|
||||||
|
std::vector<NodeID>().swap(trafficLightNodes);
|
||||||
|
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
|
||||||
|
DeallocatingVector<EdgeBasedEdge> edgeBasedEdgeList;
|
||||||
|
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
|
||||||
|
std::vector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
|
||||||
|
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
|
||||||
|
delete edgeBasedGraphFactory;
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Writing info on original (node-based) nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
INFO("writing node map ...");
|
||||||
|
std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary);
|
||||||
|
mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
|
||||||
|
mapOutFile.close();
|
||||||
|
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
|
||||||
|
|
||||||
|
double expansionHasFinishedTime = get_timestamp() - startupTime;
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Building grid-like nearest-neighbor data structure
|
||||||
|
*/
|
||||||
|
|
||||||
|
INFO("building r-tree ...");
|
||||||
|
StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode> * rtree =
|
||||||
|
new StaticRTree<EdgeBasedGraphFactory::EdgeBasedNode>(
|
||||||
|
nodeBasedEdgeList,
|
||||||
|
rtree_nodes_path.c_str(),
|
||||||
|
rtree_leafs_path.c_str()
|
||||||
|
);
|
||||||
|
delete rtree;
|
||||||
|
IteratorbasedCRC32<std::vector<EdgeBasedGraphFactory::EdgeBasedNode> > crc32;
|
||||||
|
unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() );
|
||||||
|
nodeBasedEdgeList.clear();
|
||||||
|
INFO("CRC32 based checksum is " << crc32OfNodeBasedEdgeList);
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Contracting the edge-expanded graph
|
||||||
|
*/
|
||||||
|
|
||||||
|
INFO("initializing contractor");
|
||||||
|
Contractor* contractor = new Contractor( edgeBasedNodeNumber, edgeBasedEdgeList );
|
||||||
|
double contractionStartedTimestamp(get_timestamp());
|
||||||
|
contractor->Run();
|
||||||
|
INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");
|
||||||
|
|
||||||
|
DeallocatingVector< QueryEdge > contractedEdgeList;
|
||||||
|
contractor->GetEdges( contractedEdgeList );
|
||||||
|
delete contractor;
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Sorting contracted edges in a way that the static query graph can read some in in-place.
|
||||||
|
*/
|
||||||
|
|
||||||
|
INFO("Building Node Array");
|
||||||
|
std::sort(contractedEdgeList.begin(), contractedEdgeList.end());
|
||||||
|
unsigned numberOfNodes = 0;
|
||||||
|
unsigned numberOfEdges = contractedEdgeList.size();
|
||||||
|
INFO("Serializing compacted graph of " << numberOfEdges << " edges");
|
||||||
|
std::ofstream edgeOutFile(graphOut.c_str(), std::ios::binary);
|
||||||
|
|
||||||
|
BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) {
|
||||||
|
if(edge.source > numberOfNodes) {
|
||||||
|
numberOfNodes = edge.source;
|
||||||
|
}
|
||||||
|
if(edge.target > numberOfNodes) {
|
||||||
|
numberOfNodes = edge.target;
|
||||||
}
|
}
|
||||||
//Serialize edges
|
|
||||||
edgeOutFile.write((char*) ¤tEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
|
|
||||||
++edge;
|
|
||||||
++usedEdgeCounter;
|
|
||||||
}
|
}
|
||||||
}
|
numberOfNodes+=1;
|
||||||
double endTime = (get_timestamp() - startupTime);
|
|
||||||
INFO("Expansion : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec");
|
|
||||||
INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec");
|
|
||||||
|
|
||||||
edgeOutFile.close();
|
std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
|
||||||
//cleanedEdgeList.clear();
|
_nodes.resize( numberOfNodes + 1 );
|
||||||
_nodes.clear();
|
|
||||||
INFO("finished preprocessing");
|
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
||||||
|
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
|
||||||
|
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
|
||||||
|
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
|
||||||
|
++edge;
|
||||||
|
_nodes[node].firstEdge = position; //=edge
|
||||||
|
position += edge - lastEdge; //remove
|
||||||
|
}
|
||||||
|
++numberOfNodes;
|
||||||
|
//Serialize numberOfNodes, nodes
|
||||||
|
edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
|
||||||
|
edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned));
|
||||||
|
edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
|
||||||
|
//Serialize number of Edges
|
||||||
|
edgeOutFile.write((char*) &position, sizeof(unsigned));
|
||||||
|
--numberOfNodes;
|
||||||
|
edge = 0;
|
||||||
|
int usedEdgeCounter = 0;
|
||||||
|
StaticGraph<EdgeData>::_StrEdge currentEdge;
|
||||||
|
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
|
||||||
|
for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
|
||||||
|
assert(node != contractedEdgeList[edge].target);
|
||||||
|
currentEdge.target = contractedEdgeList[edge].target;
|
||||||
|
currentEdge.data = contractedEdgeList[edge].data;
|
||||||
|
if(currentEdge.data.distance <= 0) {
|
||||||
|
INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance);
|
||||||
|
ERR("Failed at edges of node " << node << " of " << numberOfNodes);
|
||||||
|
}
|
||||||
|
//Serialize edges
|
||||||
|
edgeOutFile.write((char*) ¤tEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
|
||||||
|
++edge;
|
||||||
|
++usedEdgeCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double endTime = (get_timestamp() - startupTime);
|
||||||
|
INFO("Expansion : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec");
|
||||||
|
INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec");
|
||||||
|
|
||||||
|
edgeOutFile.close();
|
||||||
|
//cleanedEdgeList.clear();
|
||||||
|
_nodes.clear();
|
||||||
|
INFO("finished preprocessing");
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
ERR("Exception occured: " << e.what());
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
or see http://www.gnu.org/licenses/agpl.txt.
|
or see http://www.gnu.org/licenses/agpl.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "typedefs.h"
|
|
||||||
#include "Extractor/ExtractorCallbacks.h"
|
#include "Extractor/ExtractorCallbacks.h"
|
||||||
#include "Extractor/ExtractionContainers.h"
|
#include "Extractor/ExtractionContainers.h"
|
||||||
#include "Extractor/ScriptingEnvironment.h"
|
#include "Extractor/ScriptingEnvironment.h"
|
||||||
@ -34,6 +28,13 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "Util/MachineInfo.h"
|
#include "Util/MachineInfo.h"
|
||||||
#include "Util/OpenMPWrapper.h"
|
#include "Util/OpenMPWrapper.h"
|
||||||
#include "Util/StringUtil.h"
|
#include "Util/StringUtil.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
typedef BaseConfiguration ExtractorConfiguration;
|
typedef BaseConfiguration ExtractorConfiguration;
|
||||||
|
|
||||||
@ -84,11 +85,11 @@ int main (int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned amountOfRAM = 1;
|
unsigned amountOfRAM = 1;
|
||||||
unsigned installedRAM = GetPhysicalmemory();
|
unsigned installedRAM = GetPhysicalmemory();
|
||||||
if(installedRAM < 2048264) {
|
if(installedRAM < 2048264) {
|
||||||
WARN("Machine has less than 2GB RAM.");
|
WARN("Machine has less than 2GB RAM.");
|
||||||
}
|
}
|
||||||
|
|
||||||
StringMap stringMap;
|
StringMap stringMap;
|
||||||
ExtractionContainers externalMemory;
|
ExtractionContainers externalMemory;
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ int main (int argc, char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
parser = new XMLParser(argv[1], extractCallBacks, scriptingEnvironment);
|
parser = new XMLParser(argv[1], extractCallBacks, scriptingEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!parser->ReadHeader()) {
|
if(!parser->ReadHeader()) {
|
||||||
ERR("Parser not initialized!");
|
ERR("Parser not initialized!");
|
||||||
}
|
}
|
||||||
|
@ -41,14 +41,14 @@ Feature: Bike - Squares and other areas
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | b | |
|
| a | b | xa |
|
||||||
| a | d | |
|
| a | d | xa |
|
||||||
| b | c | |
|
| b | c | xa |
|
||||||
| c | b | |
|
| c | b | xa |
|
||||||
| c | d | |
|
| c | d | xa |
|
||||||
| d | c | |
|
| d | c | xa |
|
||||||
| d | a | |
|
| d | a | xa |
|
||||||
| a | d | |
|
| a | d | xa |
|
||||||
|
|
||||||
@parking
|
@parking
|
||||||
Scenario: Bike - parking areas
|
Scenario: Bike - parking areas
|
||||||
@ -100,4 +100,4 @@ Feature: Bike - Squares and other areas
|
|||||||
| c | d | abcda |
|
| c | d | abcda |
|
||||||
| d | c | abcda |
|
| d | c | abcda |
|
||||||
| d | a | abcda |
|
| d | a | abcda |
|
||||||
| a | d | abcda |
|
| a | d | abcda |
|
89
features/bicycle/mode.feature
Normal file
89
features/bicycle/mode.feature
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
@routing @bicycle @mode
|
||||||
|
Feature: Bike - Mode flag
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "bicycle"
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Scenario: Bike - Mode when using a ferry
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | route | duration |
|
||||||
|
| ab | primary | | |
|
||||||
|
| bc | | ferry | 0:01 |
|
||||||
|
| cd | primary | | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | modes |
|
||||||
|
| a | d | ab,bc,cd | head,right,left, destination | bike,ferry,bike |
|
||||||
|
| d | a | cd,bc,ab | head,right,left, destination | bike,ferry,bike |
|
||||||
|
| c | a | bc,ab | head,left,destination | ferry,bike |
|
||||||
|
| d | b | cd,bc | head,right,destination | bike,ferry |
|
||||||
|
| a | c | ab,bc | head,right,destination | bike,ferry |
|
||||||
|
| b | d | bc,cd | head,left,destination | ferry,bike |
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Scenario: Bike - Mode when pushing bike against oneways
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | oneway |
|
||||||
|
| ab | primary | |
|
||||||
|
| bc | primary | yes |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | modes |
|
||||||
|
| a | d | ab,bc,cd | head,right,left,destination | bike,push,bike |
|
||||||
|
| d | a | cd,bc,ab | head,right,left,destination | bike,push,bike |
|
||||||
|
| c | a | bc,ab | head,left,destination | push,bike |
|
||||||
|
| d | b | cd,bc | head,right,destination | bike,push |
|
||||||
|
| a | c | ab,bc | head,right,destination | bike,push |
|
||||||
|
| b | d | bc,cd | head,left,destination | push,bike |
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Scenario: Bike - Mode when pushing on pedestrain streets
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| bc | pedestrian |
|
||||||
|
| cd | primary |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | modes |
|
||||||
|
| a | d | ab,bc,cd | head,right,left,destination | bike,push,bike |
|
||||||
|
| d | a | cd,bc,ab | head,right,left,destination | bike,push,bike |
|
||||||
|
| c | a | bc,ab | head,left,destination | push,bike |
|
||||||
|
| d | b | cd,bc | head,right,destination | bike,push |
|
||||||
|
| a | c | ab,bc | head,right,destination | bike,push |
|
||||||
|
| b | d | bc,cd | head,left,destination | push,bike |
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Scenario: Bike - Mode when pushing on pedestrain areas
|
||||||
|
Given the node map
|
||||||
|
| a | b | | |
|
||||||
|
| | c | d | f |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | area |
|
||||||
|
| ab | primary | |
|
||||||
|
| bcd | pedestrian | yes |
|
||||||
|
| df | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | modes |
|
||||||
|
| a | f | ab,bcd,df | bike,push,bike |
|
||||||
|
| f | a | df,bcd,ab | bike,push,bike |
|
||||||
|
| d | a | bcd,ab | push,bike |
|
||||||
|
| f | b | df,bcd | bike,push |
|
||||||
|
| a | d | ab,bcd | bike,push |
|
||||||
|
| b | f | bcd,df | push,bike |
|
@ -10,14 +10,15 @@ Feature: Bike - Street names in instructions
|
|||||||
| | c |
|
| | c |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name |
|
| nodes | name |
|
||||||
| ab | My Way |
|
| ab | My Way |
|
||||||
| bc | Your Way |
|
| bc | Your Way |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | c | My Way,Your Way |
|
| a | c | My Way,Your Way |
|
||||||
|
|
||||||
|
@unnamed
|
||||||
Scenario: Bike - Use way type to describe unnamed ways
|
Scenario: Bike - Use way type to describe unnamed ways
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c | d |
|
| a | b | c | d |
|
||||||
@ -25,8 +26,24 @@ Feature: Bike - Street names in instructions
|
|||||||
And the ways
|
And the ways
|
||||||
| nodes | highway | name |
|
| nodes | highway | name |
|
||||||
| ab | cycleway | |
|
| ab | cycleway | |
|
||||||
| bcd | track | |
|
| bcd | track | |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | d | cycleway,track |
|
| a | d | {highway:cycleway},{highway:track} |
|
||||||
|
|
||||||
|
@area @names @todo
|
||||||
|
Scenario: Bike - name on streets overlapping an area
|
||||||
|
Given the node map
|
||||||
|
| x | a | b | y |
|
||||||
|
| | d | c | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | area |
|
||||||
|
| xaby | residential | |
|
||||||
|
| abcda | residential | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| x | y | xaby |
|
||||||
|
| y | x | xaby |
|
||||||
|
@ -112,3 +112,17 @@ Usually we can push bikes against oneways, but we use foot=no to prevent this in
|
|||||||
| no | roundabout | | yes | x | |
|
| no | roundabout | | yes | x | |
|
||||||
| no | roundabout | | no | x | |
|
| no | roundabout | | no | x | |
|
||||||
| no | roundabout | | -1 | x | |
|
| no | roundabout | | -1 | x | |
|
||||||
|
|
||||||
|
Scenario: Bike - Two consecutive oneways
|
||||||
|
Given the node map
|
||||||
|
| a | b | c |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| bc | yes |
|
||||||
|
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | c | ab,bc |
|
@ -85,3 +85,40 @@ Feature: Bike - Accessability of different way types
|
|||||||
Then routability should be
|
Then routability should be
|
||||||
| junction | forw | backw |
|
| junction | forw | backw |
|
||||||
| roundabout | x | |
|
| roundabout | x | |
|
||||||
|
|
||||||
|
Scenario: Bike - Instructions when pushing bike on oneways
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | oneway |
|
||||||
|
| ab | primary | |
|
||||||
|
| bc | primary | yes |
|
||||||
|
| cd | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns |
|
||||||
|
| a | d | ab,bc,cd | head,right,left,destination |
|
||||||
|
| d | a | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination |
|
||||||
|
| c | a | bc,ab | head,leave_contraflow,destination |
|
||||||
|
| d | b | cd,bc | head,enter_contraflow,destination |
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Scenario: Bike - Instructions when pushing bike on footway/pedestrian, etc.
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway |
|
||||||
|
| ab | primary |
|
||||||
|
| bc | footway |
|
||||||
|
| cd | primary |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns |
|
||||||
|
| a | d | ab,bc,cd | head,right,left,destination |
|
||||||
|
| d | a | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination |
|
||||||
|
| c | a | bc,ab | head,leave_contraflow,destination |
|
||||||
|
| d | b | cd,bc | head,enter_contraflow,destination |
|
41
features/bicycle/ref.feature
Normal file
41
features/bicycle/ref.feature
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@routing @bicycle @ref @name
|
||||||
|
Feature: Bike - Way ref
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "bicycle"
|
||||||
|
|
||||||
|
Scenario: Bike - Way with both name and ref
|
||||||
|
Given the node map
|
||||||
|
| a | b |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | ref |
|
||||||
|
| ab | Utopia Drive | E7 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | b | Utopia Drive / E7 |
|
||||||
|
|
||||||
|
Scenario: Bike - Way with only ref
|
||||||
|
Given the node map
|
||||||
|
| a | b |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | ref |
|
||||||
|
| ab | | E7 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | b | E7 |
|
||||||
|
|
||||||
|
Scenario: Bike - Way with only name
|
||||||
|
Given the node map
|
||||||
|
| a | b |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name |
|
||||||
|
| ab | Utopia Drive |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | b | Utopia Drive |
|
@ -31,7 +31,7 @@ Feature: Car - Max speed restrictions
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | b | ab | 144s ~10% |
|
| a | b | ab | 144s ~10% |
|
||||||
| b | c | bc | 63s ~10% |
|
| b | c | bc | 42s ~10% |
|
||||||
|
|
||||||
Scenario: Car - Forward/backward maxspeed
|
Scenario: Car - Forward/backward maxspeed
|
||||||
Given the shortcuts
|
Given the shortcuts
|
||||||
|
@ -56,4 +56,18 @@ Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tag
|
|||||||
| primary | | -1 | -1 | | x |
|
| primary | | -1 | -1 | | x |
|
||||||
| primary | roundabout | | yes | x | |
|
| primary | roundabout | | yes | x | |
|
||||||
| primary | roundabout | | no | x | |
|
| primary | roundabout | | no | x | |
|
||||||
| primary | roundabout | | -1 | x | |
|
| primary | roundabout | | -1 | x | |
|
||||||
|
|
||||||
|
Scenario: Car - Two consecutive oneways
|
||||||
|
Given the node map
|
||||||
|
| a | b | c |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| bc | yes |
|
||||||
|
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | c | ab,bc |
|
@ -3,23 +3,24 @@ Feature: Car - Handle ferryshuttle train routes
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "car"
|
Given the profile "car"
|
||||||
|
|
||||||
Scenario: Car - Use a ferry route
|
Scenario: Car - Use a ferry route
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c | | |
|
| a | b | c | | | |
|
||||||
| | | d | | |
|
| | | d | | | |
|
||||||
| | | e | f | g |
|
| | | e | f | g | h |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | highway | route | bicycle |
|
| nodes | highway | route | bicycle |
|
||||||
| abc | primary | | |
|
| abc | primary | | |
|
||||||
| cde | | shuttle_train | yes |
|
| cde | | shuttle_train | yes |
|
||||||
| ef | primary | | |
|
| ef | primary | | |
|
||||||
| fg | | ferry_man | |
|
| fg | | ferry_man | |
|
||||||
|
| gh | primary | | no |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | g | abc,cde,ef |
|
| a | f | abc,cde,ef |
|
||||||
| b | f | abc,cde,ef |
|
| b | f | abc,cde,ef |
|
||||||
| e | c | cde |
|
| e | c | cde |
|
||||||
| e | b | cde,abc |
|
| e | b | cde,abc |
|
||||||
@ -27,5 +28,6 @@ Feature: Car - Handle ferryshuttle train routes
|
|||||||
| c | e | cde |
|
| c | e | cde |
|
||||||
| c | f | cde,ef |
|
| c | f | cde,ef |
|
||||||
| f | g | |
|
| f | g | |
|
||||||
|
| g | h | gh |
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,12 +18,13 @@ Given /^the node map$/ do |table|
|
|||||||
unless name.empty?
|
unless name.empty?
|
||||||
raise "*** node invalid name '#{name}', must be single characters" unless name.size == 1
|
raise "*** node invalid name '#{name}', must be single characters" unless name.size == 1
|
||||||
raise "*** invalid node name '#{name}', must me alphanumeric" unless name.match /[a-z0-9]/
|
raise "*** invalid node name '#{name}', must me alphanumeric" unless name.match /[a-z0-9]/
|
||||||
raise "*** duplicate node '#{name}'" if name_node_hash[name]
|
if name.match /[a-z]/
|
||||||
node = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, ORIGIN[0]+ci*@zoom, ORIGIN[1]-ri*@zoom
|
raise "*** duplicate node '#{name}'" if name_node_hash[name]
|
||||||
node << { :name => name }
|
add_osm_node name, *table_coord_to_lonlat(ci,ri)
|
||||||
node.uid = OSM_UID
|
else
|
||||||
osm_db << node
|
raise "*** duplicate node '#{name}'" if location_hash[name]
|
||||||
name_node_hash[name] = node
|
add_location name, *table_coord_to_lonlat(ci,ri)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -32,21 +33,18 @@ end
|
|||||||
Given /^the node locations$/ do |table|
|
Given /^the node locations$/ do |table|
|
||||||
table.hashes.each do |row|
|
table.hashes.each do |row|
|
||||||
name = row['node']
|
name = row['node']
|
||||||
raise "*** node invalid name '#{name}', must be single characters" unless name.size == 1
|
raise "*** duplicate node '#{name}'" if find_node_by_name name
|
||||||
raise "*** invalid node name '#{name}', must me alphanumeric" unless name.match /[a-z0-9]/
|
if name.match /[a-z]/
|
||||||
raise "*** duplicate node '#{name}'" if name_node_hash[name]
|
add_osm_node name, row['lon'].to_f, row['lat'].to_f
|
||||||
node = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, row['lon'].to_f, row['lat'].to_f
|
else
|
||||||
node << { :name => name }
|
add_location name, row['lon'].to_f, row['lat'].to_f
|
||||||
node.uid = OSM_UID
|
end
|
||||||
osm_db << node
|
|
||||||
name_node_hash[name] = node
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Given /^the nodes$/ do |table|
|
Given /^the nodes$/ do |table|
|
||||||
table.hashes.each do |row|
|
table.hashes.each do |row|
|
||||||
name = row.delete 'node'
|
name = row.delete 'node'
|
||||||
raise "***invalid node name '#{c}', must be single characters" unless name.size == 1
|
|
||||||
node = find_node_by_name(name)
|
node = find_node_by_name(name)
|
||||||
raise "*** unknown node '#{c}'" unless node
|
raise "*** unknown node '#{c}'" unless node
|
||||||
node << row
|
node << row
|
||||||
@ -61,8 +59,7 @@ Given /^the ways$/ do |table|
|
|||||||
nodes = row.delete 'nodes'
|
nodes = row.delete 'nodes'
|
||||||
raise "*** duplicate way '#{nodes}'" if name_way_hash[nodes]
|
raise "*** duplicate way '#{nodes}'" if name_way_hash[nodes]
|
||||||
nodes.each_char do |c|
|
nodes.each_char do |c|
|
||||||
raise "***invalid node name '#{c}', must be single characters" unless c.size == 1
|
raise "*** ways can only use names a-z, '#{name}'" unless c.match /[a-z]/
|
||||||
raise "*** ways cannot use numbered nodes, '#{name}'" unless c.match /[a-z]/
|
|
||||||
node = find_node_by_name(c)
|
node = find_node_by_name(c)
|
||||||
raise "*** unknown node '#{c}'" unless node
|
raise "*** unknown node '#{c}'" unless node
|
||||||
way << node
|
way << node
|
||||||
|
@ -3,10 +3,10 @@ When /^I request nearest I should get$/ do |table|
|
|||||||
actual = []
|
actual = []
|
||||||
OSRMLauncher.new do
|
OSRMLauncher.new do
|
||||||
table.hashes.each_with_index do |row,ri|
|
table.hashes.each_with_index do |row,ri|
|
||||||
in_node = @name_node_hash[ row['in'] ]
|
in_node = find_node_by_name row['in']
|
||||||
raise "*** unknown in-node '#{row['in']}" unless in_node
|
raise "*** unknown in-node '#{row['in']}" unless in_node
|
||||||
|
|
||||||
out_node = @name_node_hash[ row['out'] ]
|
out_node = find_node_by_name row['out']
|
||||||
raise "*** unknown out-node '#{row['out']}" unless out_node
|
raise "*** unknown out-node '#{row['out']}" unless out_node
|
||||||
|
|
||||||
response = request_nearest("#{in_node.lat},#{in_node.lon}")
|
response = request_nearest("#{in_node.lat},#{in_node.lon}")
|
||||||
@ -42,10 +42,10 @@ When /^I request nearest I should get$/ do |table|
|
|||||||
table.routing_diff! actual
|
table.routing_diff! actual
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I route (\d+) times I should get$/ do |n,table|
|
When /^I request nearest (\d+) times I should get$/ do |n,table|
|
||||||
ok = true
|
ok = true
|
||||||
n.to_i.times do
|
n.to_i.times do
|
||||||
ok = false unless step "I route I should get", table
|
ok = false unless step "I request nearest I should get", table
|
||||||
end
|
end
|
||||||
ok
|
ok
|
||||||
end
|
end
|
@ -12,9 +12,13 @@ Then /^routability should be$/ do |table|
|
|||||||
['forw','backw','bothw'].each do |direction|
|
['forw','backw','bothw'].each do |direction|
|
||||||
if table.headers.include? direction
|
if table.headers.include? direction
|
||||||
if direction == 'forw' || direction == 'bothw'
|
if direction == 'forw' || direction == 'bothw'
|
||||||
response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}")
|
a = Location.new ORIGIN[0]+(1+WAY_SPACING*i)*@zoom, ORIGIN[1]
|
||||||
|
b = Location.new ORIGIN[0]+(3+WAY_SPACING*i)*@zoom, ORIGIN[1]
|
||||||
|
response = request_route [a,b]
|
||||||
elsif direction == 'backw' || direction == 'bothw'
|
elsif direction == 'backw' || direction == 'bothw'
|
||||||
response = request_route("#{ORIGIN[1]},#{ORIGIN[0]+(3+WAY_SPACING*i)*@zoom}","#{ORIGIN[1]},#{ORIGIN[0]+(1+WAY_SPACING*i)*@zoom}")
|
a = Location.new ORIGIN[0]+(3+WAY_SPACING*i)*@zoom, ORIGIN[1]
|
||||||
|
b = Location.new ORIGIN[0]+(1+WAY_SPACING*i)*@zoom, ORIGIN[1]
|
||||||
|
response = request_route [a,b]
|
||||||
end
|
end
|
||||||
want = shortcuts_hash[row[direction]] || row[direction] #expand shortcuts
|
want = shortcuts_hash[row[direction]] || row[direction] #expand shortcuts
|
||||||
got[direction] = route_status response
|
got[direction] = route_status response
|
||||||
@ -22,7 +26,11 @@ Then /^routability should be$/ do |table|
|
|||||||
if got[direction].empty? == false
|
if got[direction].empty? == false
|
||||||
route = way_list json['route_instructions']
|
route = way_list json['route_instructions']
|
||||||
if route != "w#{i}"
|
if route != "w#{i}"
|
||||||
got[direction] = "testing w#{i}, but got #{route}!?"
|
if row[direction].empty? == true
|
||||||
|
got[direction] = want
|
||||||
|
else
|
||||||
|
got[direction] = "testing w#{i}, but got #{route}!?"
|
||||||
|
end
|
||||||
elsif want =~ /^\d+s/
|
elsif want =~ /^\d+s/
|
||||||
time = json['route_summary']['total_time']
|
time = json['route_summary']['total_time']
|
||||||
got[direction] = "#{time}s"
|
got[direction] = "#{time}s"
|
||||||
|
@ -3,11 +3,41 @@ When /^I route I should get$/ do |table|
|
|||||||
actual = []
|
actual = []
|
||||||
OSRMLauncher.new do
|
OSRMLauncher.new do
|
||||||
table.hashes.each_with_index do |row,ri|
|
table.hashes.each_with_index do |row,ri|
|
||||||
from_node = @name_node_hash[ row['from'] ]
|
waypoints = []
|
||||||
raise "*** unknown from-node '#{row['from']}" unless from_node
|
if row['from'] and row['to']
|
||||||
to_node = @name_node_hash[ row['to'] ]
|
node = find_node_by_name(row['from'])
|
||||||
raise "*** unknown to-node '#{row['to']}" unless to_node
|
raise "*** unknown from-node '#{row['from']}" unless node
|
||||||
response = request_route("#{from_node.lat},#{from_node.lon}", "#{to_node.lat},#{to_node.lon}")
|
waypoints << node
|
||||||
|
|
||||||
|
node = find_node_by_name(row['to'])
|
||||||
|
raise "*** unknown to-node '#{row['to']}" unless node
|
||||||
|
waypoints << node
|
||||||
|
|
||||||
|
got = {'from' => row['from'], 'to' => row['to'] }
|
||||||
|
elsif row['waypoints']
|
||||||
|
row['waypoints'].split(',').each do |n|
|
||||||
|
node = find_node_by_name(n.strip)
|
||||||
|
raise "*** unknown waypoint node '#{n.strip}" unless node
|
||||||
|
waypoints << node
|
||||||
|
end
|
||||||
|
got = {'waypoints' => row['waypoints'] }
|
||||||
|
else
|
||||||
|
raise "*** no waypoints"
|
||||||
|
end
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
row.each_pair do |k,v|
|
||||||
|
if k =~ /param:(.*)/
|
||||||
|
if v=='(nil)'
|
||||||
|
params[$1]=nil
|
||||||
|
elsif v!=nil
|
||||||
|
params[$1]=v
|
||||||
|
end
|
||||||
|
got[k]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
response = request_route(waypoints, params)
|
||||||
if response.code == "200" && response.body.empty? == false
|
if response.code == "200" && response.body.empty? == false
|
||||||
json = JSON.parse response.body
|
json = JSON.parse response.body
|
||||||
if json['status'] == 0
|
if json['status'] == 0
|
||||||
@ -15,10 +45,10 @@ When /^I route I should get$/ do |table|
|
|||||||
bearings = bearing_list json['route_instructions']
|
bearings = bearing_list json['route_instructions']
|
||||||
compasses = compass_list json['route_instructions']
|
compasses = compass_list json['route_instructions']
|
||||||
turns = turn_list json['route_instructions']
|
turns = turn_list json['route_instructions']
|
||||||
|
modes = mode_list json['route_instructions']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
got = {'from' => row['from'], 'to' => row['to'] }
|
|
||||||
if table.headers.include? 'start'
|
if table.headers.include? 'start'
|
||||||
got['start'] = instructions ? json['route_summary']['start_point'] : nil
|
got['start'] = instructions ? json['route_summary']['start_point'] : nil
|
||||||
end
|
end
|
||||||
@ -46,6 +76,9 @@ When /^I route I should get$/ do |table|
|
|||||||
if table.headers.include? 'turns'
|
if table.headers.include? 'turns'
|
||||||
got['turns'] = turns
|
got['turns'] = turns
|
||||||
end
|
end
|
||||||
|
if table.headers.include? 'modes'
|
||||||
|
got['modes'] = modes
|
||||||
|
end
|
||||||
if table.headers.include? '#' # comment column
|
if table.headers.include? '#' # comment column
|
||||||
got['#'] = row['#'] # copy value so it always match
|
got['#'] = row['#'] # copy value so it always match
|
||||||
end
|
end
|
||||||
|
@ -14,9 +14,19 @@ DEFAULT_SPEEDPROFILE = 'bicycle'
|
|||||||
WAY_SPACING = 100
|
WAY_SPACING = 100
|
||||||
DEFAULT_GRID_SIZE = 100 #meters
|
DEFAULT_GRID_SIZE = 100 #meters
|
||||||
PROFILES_PATH = '../profiles'
|
PROFILES_PATH = '../profiles'
|
||||||
|
BIN_PATH = '../build'
|
||||||
|
|
||||||
ORIGIN = [1,1]
|
ORIGIN = [1,1]
|
||||||
|
|
||||||
|
class Location
|
||||||
|
attr_accessor :lon,:lat
|
||||||
|
|
||||||
|
def initialize lon,lat
|
||||||
|
@lat = lat
|
||||||
|
@lon = lon
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def sanitized_scenario_title
|
def sanitized_scenario_title
|
||||||
@sanitized_scenario_title ||= @scenario_title.gsub /[^0-9A-Za-z.\-]/, '_'
|
@sanitized_scenario_title ||= @scenario_title.gsub /[^0-9A-Za-z.\-]/, '_'
|
||||||
end
|
end
|
||||||
@ -32,10 +42,10 @@ def build_ways_from_table table
|
|||||||
#add one unconnected way for each row
|
#add one unconnected way for each row
|
||||||
table.hashes.each_with_index do |row,ri|
|
table.hashes.each_with_index do |row,ri|
|
||||||
#NOTE:
|
#NOTE:
|
||||||
#currently osrm crashes when processing an isolated oneway with just 2 nodes, so we use 4
|
#currently osrm crashes when processing an isolated oneway with just 2 nodes, so we use 4 edges
|
||||||
#this is relatated to the fact that a oneway deadend doesn't make a lot of sense
|
#this is relatated to the fact that a oneway dead-end street doesn't make a lot of sense
|
||||||
|
|
||||||
#if we stack ways on different x coordinates, outability tests get messed up, because osrm might pick a neighboring way if the one test can't be used.
|
#if we stack ways on different x coordinates, routability tests get messed up, because osrm might pick a neighboring way if the one test can't be used.
|
||||||
#instead we place all lines as a string on the same y coordinate. this prevents using neightboring ways.
|
#instead we place all lines as a string on the same y coordinate. this prevents using neightboring ways.
|
||||||
|
|
||||||
#a few nodes...
|
#a few nodes...
|
||||||
@ -110,8 +120,30 @@ def build_ways_from_table table
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def table_coord_to_lonlat ci,ri
|
||||||
|
[ORIGIN[0]+ci*@zoom, ORIGIN[1]-ri*@zoom]
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_osm_node name,lon,lat
|
||||||
|
node = OSM::Node.new make_osm_id, OSM_USER, OSM_TIMESTAMP, lon, lat
|
||||||
|
node << { :name => name }
|
||||||
|
node.uid = OSM_UID
|
||||||
|
osm_db << node
|
||||||
|
name_node_hash[name] = node
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_location name,lon,lat
|
||||||
|
location_hash[name] = Location.new(lon,lat)
|
||||||
|
end
|
||||||
|
|
||||||
def find_node_by_name s
|
def find_node_by_name s
|
||||||
name_node_hash[s.to_s]
|
raise "***invalid node name '#{s}', must be single characters" unless s.size == 1
|
||||||
|
raise "*** invalid node name '#{s}', must be alphanumeric" unless s.match /[a-z0-9]/
|
||||||
|
if s.match /[a-z]/
|
||||||
|
from_node = name_node_hash[ s.to_s ]
|
||||||
|
else
|
||||||
|
from_node = location_hash[ s.to_s ]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_way_by_name s
|
def find_way_by_name s
|
||||||
@ -135,6 +167,7 @@ end
|
|||||||
def reset_osm
|
def reset_osm
|
||||||
osm_db.clear
|
osm_db.clear
|
||||||
name_node_hash.clear
|
name_node_hash.clear
|
||||||
|
location_hash.clear
|
||||||
name_way_hash.clear
|
name_way_hash.clear
|
||||||
@osm_str = nil
|
@osm_str = nil
|
||||||
@osm_hash = nil
|
@osm_hash = nil
|
||||||
@ -157,6 +190,10 @@ def name_node_hash
|
|||||||
@name_node_hash ||= {}
|
@name_node_hash ||= {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def location_hash
|
||||||
|
@location_hash ||= {}
|
||||||
|
end
|
||||||
|
|
||||||
def name_way_hash
|
def name_way_hash
|
||||||
@name_way_hash ||= {}
|
@name_way_hash ||= {}
|
||||||
end
|
end
|
||||||
@ -213,7 +250,7 @@ def reprocess
|
|||||||
unless extracted?
|
unless extracted?
|
||||||
log_preprocess_info
|
log_preprocess_info
|
||||||
log "== Extracting #{@osm_file}.osm...", :preprocess
|
log "== Extracting #{@osm_file}.osm...", :preprocess
|
||||||
unless system "../osrm-extract #{@osm_file}.osm#{'.pbf' if use_pbf} 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
|
unless system "#{BIN_PATH}/osrm-extract #{@osm_file}.osm#{'.pbf' if use_pbf} 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
|
||||||
log "*** Exited with code #{$?.exitstatus}.", :preprocess
|
log "*** Exited with code #{$?.exitstatus}.", :preprocess
|
||||||
raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}."
|
raise ExtractError.new $?.exitstatus, "osrm-extract exited with code #{$?.exitstatus}."
|
||||||
end
|
end
|
||||||
@ -222,7 +259,7 @@ def reprocess
|
|||||||
unless prepared?
|
unless prepared?
|
||||||
log_preprocess_info
|
log_preprocess_info
|
||||||
log "== Preparing #{@osm_file}.osm...", :preprocess
|
log "== Preparing #{@osm_file}.osm...", :preprocess
|
||||||
unless system "../osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
|
unless system "#{BIN_PATH}/osrm-prepare #{@osm_file}.osrm #{@osm_file}.osrm.restrictions 1>>#{PREPROCESS_LOG_FILE} 2>>#{PREPROCESS_LOG_FILE} #{PROFILES_PATH}/#{@profile}.lua"
|
||||||
log "*** Exited with code #{$?.exitstatus}.", :preprocess
|
log "*** Exited with code #{$?.exitstatus}.", :preprocess
|
||||||
raise PrepareError.new $?.exitstatus, "osrm-prepare exited with code #{$?.exitstatus}."
|
raise PrepareError.new $?.exitstatus, "osrm-prepare exited with code #{$?.exitstatus}."
|
||||||
end
|
end
|
||||||
|
@ -22,8 +22,8 @@ class FuzzyMatch
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.match_location got, want
|
def self.match_location got, want
|
||||||
match( got[0], "#{want.lat} ~0.002%" ) &&
|
match( got[0], "#{want.lat} ~0.0025%" ) &&
|
||||||
match( got[1], "#{want.lon} ~0.002%" )
|
match( got[1], "#{want.lon} ~0.0025%" )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -29,15 +29,15 @@ def lua_lib_hash
|
|||||||
end
|
end
|
||||||
|
|
||||||
def bin_extract_hash
|
def bin_extract_hash
|
||||||
@@bin_extract_hash ||= hash_of_files '../osrm-extract'
|
@@bin_extract_hash ||= hash_of_files "#{BIN_PATH}/osrm-extract"
|
||||||
end
|
end
|
||||||
|
|
||||||
def bin_prepare_hash
|
def bin_prepare_hash
|
||||||
@@bin_prepare_hash ||= hash_of_files '../osrm-prepare'
|
@@bin_prepare_hash ||= hash_of_files "#{BIN_PATH}/osrm-prepare"
|
||||||
end
|
end
|
||||||
|
|
||||||
def bin_routed_hash
|
def bin_routed_hash
|
||||||
@@bin_routed_hash ||= hash_of_files '../osrm-routed'
|
@@bin_routed_hash ||= hash_of_files "#{BIN_PATH}/osrm-routed"
|
||||||
end
|
end
|
||||||
|
|
||||||
#combine state of data, profile and binaries into a hash that identifies the exact test scenario
|
#combine state of data, profile and binaries into a hash that identifies the exact test scenario
|
||||||
|
@ -48,7 +48,7 @@ class OSRMLauncher
|
|||||||
|
|
||||||
def osrm_up
|
def osrm_up
|
||||||
return if osrm_up?
|
return if osrm_up?
|
||||||
@pid = Process.spawn(['../osrm-routed',''],:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE)
|
@pid = Process.spawn(["#{BIN_PATH}/osrm-routed",''],:out=>OSRM_ROUTED_LOG_FILE, :err=>OSRM_ROUTED_LOG_FILE)
|
||||||
end
|
end
|
||||||
|
|
||||||
def osrm_down
|
def osrm_down
|
||||||
|
@ -4,10 +4,19 @@ HOST = "http://localhost:#{OSRM_PORT}"
|
|||||||
REQUEST_TIMEOUT = 1
|
REQUEST_TIMEOUT = 1
|
||||||
DESTINATION_REACHED = 15 #OSRM instruction code
|
DESTINATION_REACHED = 15 #OSRM instruction code
|
||||||
|
|
||||||
|
class Hash
|
||||||
|
def to_param(namespace = nil)
|
||||||
|
collect do |key, value|
|
||||||
|
"#{key}=#{value}"
|
||||||
|
end.sort
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def request_path path
|
def request_path path, waypoints=[], options={}
|
||||||
@query = path
|
locs = waypoints.compact.map { |w| "loc=#{w.lat},#{w.lon}" }
|
||||||
uri = URI.parse "#{HOST}/#{path}"
|
params = (locs + options.to_param).join('&')
|
||||||
|
params = nil if params==""
|
||||||
|
uri = URI.parse ["#{HOST}/#{path}", params].compact.join('?')
|
||||||
Timeout.timeout(REQUEST_TIMEOUT) do
|
Timeout.timeout(REQUEST_TIMEOUT) do
|
||||||
Net::HTTP.get_response uri
|
Net::HTTP.get_response uri
|
||||||
end
|
end
|
||||||
@ -17,8 +26,9 @@ rescue Timeout::Error
|
|||||||
raise "*** osrm-routed did not respond."
|
raise "*** osrm-routed did not respond."
|
||||||
end
|
end
|
||||||
|
|
||||||
def request_route a,b
|
def request_route waypoints, params={}
|
||||||
request_path "viaroute?loc=#{a}&loc=#{b}&output=json&instructions=true&alt=true"
|
defaults = { 'output' => 'json', 'instructions' => true, 'alt' => false }
|
||||||
|
request_path "viaroute", waypoints, defaults.merge(params)
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_response response
|
def parse_response response
|
||||||
@ -108,9 +118,18 @@ def turn_list instructions
|
|||||||
12 => :leave_roundabout,
|
12 => :leave_roundabout,
|
||||||
13 => :stay_roundabout,
|
13 => :stay_roundabout,
|
||||||
14 => :start_end_of_street,
|
14 => :start_end_of_street,
|
||||||
15 => :destination
|
15 => :destination,
|
||||||
|
16 => :enter_contraflow,
|
||||||
|
17 => :leave_contraflow
|
||||||
}
|
}
|
||||||
instructions.
|
instructions.
|
||||||
map { |r| types[r[0].to_i].to_s }.
|
map { |r| types[r[0].to_i].to_s }.
|
||||||
join(',')
|
join(',')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mode_list instructions
|
||||||
|
instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
|
||||||
|
map { |r| r[8] }.
|
||||||
|
map { |r| (r=="" || r==nil) ? '""' : r }.
|
||||||
|
join(',')
|
||||||
|
end
|
@ -16,17 +16,17 @@ Feature: Handle bad data in a graceful manner
|
|||||||
|
|
||||||
Scenario: Only dead-end oneways
|
Scenario: Only dead-end oneways
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | c | d | e |
|
||||||
|
|
||||||
Given the ways
|
Given the ways
|
||||||
| nodes | oneway |
|
| nodes | oneway |
|
||||||
| ab | yes |
|
| abcde | yes |
|
||||||
| cb | yes |
|
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | b | ab |
|
| b | d | abcde |
|
||||||
|
|
||||||
|
@todo
|
||||||
Scenario: Start/end point at the same location
|
Scenario: Start/end point at the same location
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b |
|
| a | b |
|
||||||
@ -58,27 +58,29 @@ Feature: Handle bad data in a graceful manner
|
|||||||
| k | -78 | 0 |
|
| k | -78 | 0 |
|
||||||
| l | -80 | 0 |
|
| l | -80 | 0 |
|
||||||
| m | -82 | 0 |
|
| m | -82 | 0 |
|
||||||
| n | -87 | 0 |
|
# | n | -87 | 0 |
|
||||||
| o | -89 | 0 |
|
# | o | -89 | 0 |
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes |
|
| nodes |
|
||||||
| ab |
|
# | ab |
|
||||||
| bc |
|
| bc |
|
||||||
| cd |
|
| cd |
|
||||||
| de |
|
| de |
|
||||||
| kl |
|
| kl |
|
||||||
| lm |
|
| lm |
|
||||||
| mn |
|
# | mn |
|
||||||
| no |
|
# | no |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | b | |
|
# | a | b | cd |
|
||||||
| b | c | |
|
# | b | c | cd |
|
||||||
| a | d | |
|
# | a | d | cd |
|
||||||
| c | d | cd |
|
# | c | d | cd |
|
||||||
| l | m | lm |
|
| d | e | de |
|
||||||
| o | l | |
|
# | k | l | kl |
|
||||||
| n | m | |
|
# | l | m | lm |
|
||||||
| o | n | |
|
# | o | l | lm |
|
||||||
|
# | n | m | lm |
|
||||||
|
# | o | n | lm |
|
||||||
|
93
features/testbot/bearing_param.feature
Normal file
93
features/testbot/bearing_param.feature
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
@routing @bearing_param @todo
|
||||||
|
Feature: Bearing parameter
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
And a grid size of 10 meters
|
||||||
|
|
||||||
|
Scenario: Testbot - Intial bearing in simple case
|
||||||
|
Given the node map
|
||||||
|
| a | |
|
||||||
|
| 0 | c |
|
||||||
|
| b | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ac |
|
||||||
|
| bc |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | param:bearing | route | bearing |
|
||||||
|
| 0 | c | 0 | bc | 45 |
|
||||||
|
| 0 | c | 45 | bc | 45 |
|
||||||
|
| 0 | c | 85 | bc | 45 |
|
||||||
|
| 0 | c | 95 | ac | 135 |
|
||||||
|
| 0 | c | 135 | ac | 135 |
|
||||||
|
| 0 | c | 180 | ac | 135 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Initial bearing on split way
|
||||||
|
Given the node map
|
||||||
|
| d | | | | | 1 | | | | | c |
|
||||||
|
| a | | | | | 0 | | | | | b |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ab | yes |
|
||||||
|
| bc | yes |
|
||||||
|
| cd | yes |
|
||||||
|
| da | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | param:bearing | route | bearing |
|
||||||
|
| 0 | b | 10 | ab | 90 |
|
||||||
|
| 0 | b | 90 | ab | 90 |
|
||||||
|
| 0 | b | 170 | ab | 90 |
|
||||||
|
| 0 | b | 190 | cd,da,ab | 270 |
|
||||||
|
| 0 | b | 270 | cd,da,ab | 270 |
|
||||||
|
| 0 | b | 350 | cd,da,ab | 270 |
|
||||||
|
| 1 | d | 10 | cd | 90 |
|
||||||
|
| 1 | d | 90 | cd | 90 |
|
||||||
|
| 1 | d | 170 | cd | 90 |
|
||||||
|
| 1 | d | 190 | ab,bc,cd | 270 |
|
||||||
|
| 1 | d | 270 | ab,bc,cd | 270 |
|
||||||
|
| 1 | d | 350 | ab,bc,cd | 270 |
|
||||||
|
|
||||||
|
Scenario: Testbot - Initial bearing in all direction
|
||||||
|
Given the node map
|
||||||
|
| h | | | a | | | b |
|
||||||
|
| | | | | | | |
|
||||||
|
| | | p | i | j | | |
|
||||||
|
| g | | o | 0 | k | | c |
|
||||||
|
| | | n | m | l | | |
|
||||||
|
| | | | | | | |
|
||||||
|
| f | | | e | | | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway |
|
||||||
|
| ia | yes |
|
||||||
|
| jb | yes |
|
||||||
|
| kc | yes |
|
||||||
|
| ld | yes |
|
||||||
|
| me | yes |
|
||||||
|
| nf | yes |
|
||||||
|
| og | yes |
|
||||||
|
| ph | yes |
|
||||||
|
| ab | yes |
|
||||||
|
| bc | yes |
|
||||||
|
| cd | yes |
|
||||||
|
| de | yes |
|
||||||
|
| ef | yes |
|
||||||
|
| fg | yes |
|
||||||
|
| gh | yes |
|
||||||
|
| ha | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | param:bearing | route | bearing |
|
||||||
|
| 0 | a | 0 | ia | 0 |
|
||||||
|
| 0 | a | 45 | jb,bc,cd,de,ef,fg,gh,ha | 45 |
|
||||||
|
| 0 | a | 90 | kc,cd,de,ef,fg,gh,ha | 90 |
|
||||||
|
| 0 | a | 135 | ld,de,ef,fg,gh,ha | 135 |
|
||||||
|
| 0 | a | 180 | me,de,ef,fg,gh,ha | 180 |
|
||||||
|
| 0 | a | 225 | nf,ef,fg,gh,ha | 225 |
|
||||||
|
| 0 | a | 270 | og,gh,ha | 270 |
|
||||||
|
| 0 | a | 315 | pn,ha | 315 |
|
23
features/testbot/bug.feature
Normal file
23
features/testbot/bug.feature
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
@routing @testbot @bug @todo
|
||||||
|
Feature: Testbot - Things that looks like bugs
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
Scenario: Testbot - Triangle problem
|
||||||
|
Given the node map
|
||||||
|
| | | | d |
|
||||||
|
| a | b | c | |
|
||||||
|
| | | | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | oneway |
|
||||||
|
| abc | primary | |
|
||||||
|
| cd | primary | yes |
|
||||||
|
| ce | river | |
|
||||||
|
| de | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| d | c | de,ce |
|
||||||
|
| e | d | de |
|
38
features/testbot/example.feature
Normal file
38
features/testbot/example.feature
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@routing @testbot @example
|
||||||
|
Feature: Testbot - Walkthrough
|
||||||
|
|
||||||
|
# A complete walk-through of how this data is processed can be found at:
|
||||||
|
# https://github.com/DennisOSRM/Project-OSRM/wiki/Processing-Flow
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
Scenario: Testbot - Processing Flow
|
||||||
|
Given the node map
|
||||||
|
| | | | d |
|
||||||
|
| a | b | c | |
|
||||||
|
| | | | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | oneway |
|
||||||
|
| abc | primary | |
|
||||||
|
| cd | primary | yes |
|
||||||
|
| ce | river | |
|
||||||
|
| de | primary | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route |
|
||||||
|
| a | b | abc |
|
||||||
|
| a | c | abc |
|
||||||
|
| a | d | abc,cd |
|
||||||
|
| a | e | abc,ce |
|
||||||
|
| b | a | abc |
|
||||||
|
| b | c | abc |
|
||||||
|
| b | d | abc,cd |
|
||||||
|
| b | e | abc,ce |
|
||||||
|
| d | a | de,ce,abc |
|
||||||
|
| d | b | de,ce,abc |
|
||||||
|
| d | e | de |
|
||||||
|
| e | a | ce,abc |
|
||||||
|
| e | b | ce,abc |
|
||||||
|
| e | c | ce |
|
26
features/testbot/mode.feature
Normal file
26
features/testbot/mode.feature
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@routing @testbot @mode
|
||||||
|
Feature: Testbot - Mode flag
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Scenario: Bike - Mode
|
||||||
|
Given the node map
|
||||||
|
| a | b | |
|
||||||
|
| | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | route | duration |
|
||||||
|
| ab | primary | | |
|
||||||
|
| bc | | ferry | 0:01 |
|
||||||
|
| cd | primary | | |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | route | turns | modes |
|
||||||
|
| a | d | ab,bc,cd | head,right,left,destination | bot,ferry,bot |
|
||||||
|
| d | a | cd,bc,ab | head,right left,destination | bot,ferry,bot |
|
||||||
|
| c | a | bc,ab | head,left,destination | ferry,bot |
|
||||||
|
| d | b | cd,bc | head,right,destination | bot,ferry |
|
||||||
|
| a | c | ab,bc | head,right,destination | bot,ferry |
|
||||||
|
| b | d | bc,cd | head,left,destination | ferry,bot |
|
@ -4,7 +4,7 @@ Testbot uses a signal penalty of 7s.
|
|||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
|
|
||||||
Scenario: Traffic signals should incur a delay, without changing distance
|
Scenario: Traffic signals should incur a delay, without changing distance
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | c |
|
||||||
@ -44,11 +44,8 @@ Testbot uses a signal penalty of 7s.
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | b | abc | 10s +-1 |
|
|
||||||
| a | c | abc | 27s +-1 |
|
| a | c | abc | 27s +-1 |
|
||||||
| d | e | def | 20s +-1 |
|
|
||||||
| d | f | def | 47s +-1 |
|
| d | f | def | 47s +-1 |
|
||||||
| g | h | ghi | 30s +-1 |
|
|
||||||
| g | i | ghi | 67s +-1 |
|
| g | i | ghi | 67s +-1 |
|
||||||
|
|
||||||
Scenario: Passing multiple traffic signals should incur a accumulated delay
|
Scenario: Passing multiple traffic signals should incur a accumulated delay
|
||||||
@ -69,6 +66,7 @@ Testbot uses a signal penalty of 7s.
|
|||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | e | abcde | 61s +-1 |
|
| a | e | abcde | 61s +-1 |
|
||||||
|
|
||||||
|
@todo
|
||||||
Scenario: Signal penalty should not depend on way type
|
Scenario: Signal penalty should not depend on way type
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | c |
|
||||||
@ -114,6 +112,7 @@ Testbot uses a signal penalty of 7s.
|
|||||||
| from | to | route | time |
|
| from | to | route | time |
|
||||||
| a | e | abcde | 61s +-1 |
|
| a | e | abcde | 61s +-1 |
|
||||||
|
|
||||||
|
@todo
|
||||||
Scenario: Starting or ending at a traffic signal should not incur a delay
|
Scenario: Starting or ending at a traffic signal should not incur a delay
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | b | c |
|
| a | b | c |
|
||||||
@ -154,7 +153,7 @@ Testbot uses a signal penalty of 7s.
|
|||||||
And the node map
|
And the node map
|
||||||
| a | | b | | c |
|
| a | | b | | c |
|
||||||
| | | d | | |
|
| | | d | | |
|
||||||
|
|
||||||
And the nodes
|
And the nodes
|
||||||
| node | highway |
|
| node | highway |
|
||||||
| b | traffic_signals |
|
| b | traffic_signals |
|
||||||
@ -163,7 +162,7 @@ Testbot uses a signal penalty of 7s.
|
|||||||
| nodes | highway |
|
| nodes | highway |
|
||||||
| abc | primary |
|
| abc | primary |
|
||||||
| adc | primary |
|
| adc | primary |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | route |
|
| from | to | route |
|
||||||
| a | c | adc |
|
| a | c | adc |
|
@ -98,7 +98,7 @@ Feature: Snap start/end point to the nearest way
|
|||||||
| b | x | xb |
|
| b | x | xb |
|
||||||
| c | x | xc |
|
| c | x | xc |
|
||||||
|
|
||||||
Scenario: Find edges within 1km, but not 10km
|
Scenario: Find edges within 1km, and the same from 10km
|
||||||
Given a grid size of 1000 meters
|
Given a grid size of 1000 meters
|
||||||
Given the node map
|
Given the node map
|
||||||
| p | | | | | | | | | | | i | | | | | | | | | | | j |
|
| p | | | | | | | | | | | i | | | | | | | | | | | j |
|
||||||
@ -144,11 +144,11 @@ Feature: Snap start/end point to the nearest way
|
|||||||
| x | 6 | xf |
|
| x | 6 | xf |
|
||||||
| x | 7 | xg |
|
| x | 7 | xg |
|
||||||
| x | 8 | xh |
|
| x | 8 | xh |
|
||||||
| x | i | |
|
| x | i | xa |
|
||||||
| x | j | |
|
| x | j | xb |
|
||||||
| x | k | |
|
| x | k | xc |
|
||||||
| x | l | |
|
| x | l | xd |
|
||||||
| x | m | |
|
| x | m | xe |
|
||||||
| x | n | |
|
| x | n | xf |
|
||||||
| x | o | |
|
| x | o | xg |
|
||||||
| x | p | |
|
| x | p | xh |
|
52
features/testbot/via.feature
Normal file
52
features/testbot/via.feature
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
@routing @testbot @via
|
||||||
|
Feature: Via points
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "testbot"
|
||||||
|
|
||||||
|
Scenario: Simple via point
|
||||||
|
Given the node map
|
||||||
|
| a | b | c |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route |
|
||||||
|
| a,b,c | abc |
|
||||||
|
| c,b,a | abc |
|
||||||
|
|
||||||
|
Scenario: Via point at a dead end
|
||||||
|
Given the node map
|
||||||
|
| a | b | c |
|
||||||
|
| | d | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
| bd |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route |
|
||||||
|
| a,d,c | abc,bd,bd,abc |
|
||||||
|
| c,d,a | abc,bd,bd,abc |
|
||||||
|
|
||||||
|
Scenario: Multiple via points
|
||||||
|
Given the node map
|
||||||
|
| a | | | | e | f | g | |
|
||||||
|
| | b | c | d | | | | h |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ae |
|
||||||
|
| ab |
|
||||||
|
| bcd |
|
||||||
|
| de |
|
||||||
|
| efg |
|
||||||
|
| gh |
|
||||||
|
| dh |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route |
|
||||||
|
| a,c,f,h | ab,bcd,de,efg,gh |
|
219
profile.lua
219
profile.lua
@ -1,219 +0,0 @@
|
|||||||
-- Begin of globals
|
|
||||||
require("lib/access")
|
|
||||||
|
|
||||||
barrier_whitelist = { ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true}
|
|
||||||
access_tag_whitelist = { ["yes"] = true, ["motorcar"] = true, ["motor_vehicle"] = true, ["vehicle"] = true, ["permissive"] = true, ["designated"] = true }
|
|
||||||
access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestry"] = true }
|
|
||||||
access_tag_restricted = { ["destination"] = true, ["delivery"] = true }
|
|
||||||
access_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
|
||||||
access_tags_hierachy = { "motorcar", "motor_vehicle", "vehicle", "access" }
|
|
||||||
service_tag_restricted = { ["parking_aisle"] = true }
|
|
||||||
ignore_in_grid = { ["ferry"] = true }
|
|
||||||
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
|
||||||
|
|
||||||
speed_profile = {
|
|
||||||
["motorway"] = 90,
|
|
||||||
["motorway_link"] = 75,
|
|
||||||
["trunk"] = 85,
|
|
||||||
["trunk_link"] = 70,
|
|
||||||
["primary"] = 65,
|
|
||||||
["primary_link"] = 60,
|
|
||||||
["secondary"] = 55,
|
|
||||||
["secondary_link"] = 50,
|
|
||||||
["tertiary"] = 40,
|
|
||||||
["tertiary_link"] = 30,
|
|
||||||
["unclassified"] = 25,
|
|
||||||
["residential"] = 25,
|
|
||||||
["living_street"] = 10,
|
|
||||||
["service"] = 15,
|
|
||||||
-- ["track"] = 5,
|
|
||||||
["ferry"] = 5,
|
|
||||||
["shuttle_train"] = 10,
|
|
||||||
["default"] = 50
|
|
||||||
}
|
|
||||||
|
|
||||||
take_minimum_of_speeds = false
|
|
||||||
obey_oneway = true
|
|
||||||
obey_bollards = true
|
|
||||||
use_restrictions = true
|
|
||||||
ignore_areas = true -- future feature
|
|
||||||
traffic_signal_penalty = 2
|
|
||||||
u_turn_penalty = 20
|
|
||||||
|
|
||||||
-- End of globals
|
|
||||||
|
|
||||||
function get_exceptions(vector)
|
|
||||||
for i,v in ipairs(restriction_exception_tags) do
|
|
||||||
vector:Add(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function parse_maxspeed(source)
|
|
||||||
if source == nil then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
local n = tonumber(source:match("%d*"))
|
|
||||||
if n == nil then
|
|
||||||
n = 0
|
|
||||||
end
|
|
||||||
if string.match(source, "mph") or string.match(source, "mp/h") then
|
|
||||||
n = (n*1609)/1000;
|
|
||||||
end
|
|
||||||
return math.abs(n)
|
|
||||||
end
|
|
||||||
|
|
||||||
function node_function (node)
|
|
||||||
local barrier = node.tags:Find ("barrier")
|
|
||||||
local access = Access.find_access_tag(node, access_tags_hierachy)
|
|
||||||
local traffic_signal = node.tags:Find("highway")
|
|
||||||
|
|
||||||
--flag node if it carries a traffic light
|
|
||||||
|
|
||||||
if traffic_signal == "traffic_signals" then
|
|
||||||
node.traffic_light = true;
|
|
||||||
end
|
|
||||||
|
|
||||||
-- parse access and barrier tags
|
|
||||||
if access and access ~= "" then
|
|
||||||
if access_tag_blacklist[access] then
|
|
||||||
node.bollard = true
|
|
||||||
end
|
|
||||||
elseif barrier and barrier ~= "" then
|
|
||||||
if barrier_whitelist[barrier] then
|
|
||||||
return
|
|
||||||
else
|
|
||||||
node.bollard = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function way_function (way)
|
|
||||||
-- First, get the properties of each way that we come across
|
|
||||||
local highway = way.tags:Find("highway")
|
|
||||||
local name = way.tags:Find("name")
|
|
||||||
local ref = way.tags:Find("ref")
|
|
||||||
local junction = way.tags:Find("junction")
|
|
||||||
local route = way.tags:Find("route")
|
|
||||||
local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
|
|
||||||
local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward"))
|
|
||||||
local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward"))
|
|
||||||
local barrier = way.tags:Find("barrier")
|
|
||||||
local oneway = way.tags:Find("oneway")
|
|
||||||
local cycleway = way.tags:Find("cycleway")
|
|
||||||
local duration = way.tags:Find("duration")
|
|
||||||
local service = way.tags:Find("service")
|
|
||||||
local area = way.tags:Find("area")
|
|
||||||
local access = Access.find_access_tag(way, access_tags_hierachy)
|
|
||||||
|
|
||||||
-- Second, parse the way according to these properties
|
|
||||||
|
|
||||||
if ignore_areas and ("yes" == area) then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if we are allowed to access the way
|
|
||||||
if access_tag_blacklist[access] then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the name that will be used for instructions
|
|
||||||
if "" ~= ref then
|
|
||||||
way.name = ref
|
|
||||||
elseif "" ~= name then
|
|
||||||
way.name = name
|
|
||||||
-- else
|
|
||||||
-- way.name = highway -- if no name exists, use way type
|
|
||||||
end
|
|
||||||
|
|
||||||
if "roundabout" == junction then
|
|
||||||
way.roundabout = true;
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handling ferries and piers
|
|
||||||
if (speed_profile[route] ~= nil and speed_profile[route] > 0) then
|
|
||||||
if durationIsValid(duration) then
|
|
||||||
way.duration = math.max( parseDuration(duration), 1 );
|
|
||||||
end
|
|
||||||
way.direction = Way.bidirectional
|
|
||||||
if speed_profile[route] ~= nil then
|
|
||||||
highway = route;
|
|
||||||
end
|
|
||||||
if tonumber(way.duration) < 0 then
|
|
||||||
way.speed = speed_profile[highway]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the avg speed on the way if it is accessible by road class
|
|
||||||
if (speed_profile[highway] ~= nil and way.speed == -1 ) then
|
|
||||||
if maxspeed > speed_profile[highway] then
|
|
||||||
way.speed = maxspeed
|
|
||||||
else
|
|
||||||
if 0 == maxspeed then
|
|
||||||
maxspeed = math.huge
|
|
||||||
end
|
|
||||||
way.speed = math.min(speed_profile[highway], maxspeed)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the avg speed on ways that are marked accessible
|
|
||||||
if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then
|
|
||||||
if 0 == maxspeed then
|
|
||||||
maxspeed = math.huge
|
|
||||||
end
|
|
||||||
way.speed = math.min(speed_profile["default"], maxspeed)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set access restriction flag if access is allowed under certain restrictions only
|
|
||||||
if access ~= "" and access_tag_restricted[access] then
|
|
||||||
way.is_access_restricted = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set access restriction flag if service is allowed under certain restrictions only
|
|
||||||
if service ~= "" and service_tag_restricted[service] then
|
|
||||||
way.is_access_restricted = true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set direction according to tags on way
|
|
||||||
if obey_oneway then
|
|
||||||
if oneway == "no" or oneway == "0" or oneway == "false" then
|
|
||||||
way.direction = Way.bidirectional
|
|
||||||
elseif oneway == "-1" then
|
|
||||||
way.direction = Way.opposite
|
|
||||||
elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then
|
|
||||||
way.direction = Way.oneway
|
|
||||||
else
|
|
||||||
way.direction = Way.bidirectional
|
|
||||||
end
|
|
||||||
else
|
|
||||||
way.direction = Way.bidirectional
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Override speed settings if explicit forward/backward maxspeeds are given
|
|
||||||
if maxspeed_forward ~= nil and maxspeed_forward > 0 then
|
|
||||||
if Way.bidirectional == way.direction then
|
|
||||||
way.backward_speed = way.speed
|
|
||||||
end
|
|
||||||
way.speed = maxspeed_forward
|
|
||||||
end
|
|
||||||
if maxspeed_backward ~= nil and maxspeed_backward > 0 then
|
|
||||||
way.backward_speed = maxspeed_backward
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Override general direction settings of there is a specific one for our mode of travel
|
|
||||||
|
|
||||||
if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
|
|
||||||
way.ignore_in_grid = true
|
|
||||||
end
|
|
||||||
way.type = 1
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT
|
|
||||||
|
|
||||||
function node_vector_function(vector)
|
|
||||||
for v in vector.nodes do
|
|
||||||
node_function(v)
|
|
||||||
end
|
|
||||||
end
|
|
@ -65,6 +65,24 @@ route_speeds = {
|
|||||||
["ferry"] = 5
|
["ferry"] = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
surface_speeds = {
|
||||||
|
["cobblestone:flattened"] = 10,
|
||||||
|
["paving_stones"] = 10,
|
||||||
|
["compacted"] = 10,
|
||||||
|
["cobblestone"] = 6,
|
||||||
|
["unpaved"] = 6,
|
||||||
|
["fine_gravel"] = 6,
|
||||||
|
["gravel"] = 6,
|
||||||
|
["fine_gravel"] = 6,
|
||||||
|
["pebbelstone"] = 6,
|
||||||
|
["ground"] = 6,
|
||||||
|
["dirt"] = 6,
|
||||||
|
["earth"] = 6,
|
||||||
|
["grass"] = 6,
|
||||||
|
["mud"] = 3,
|
||||||
|
["sand"] = 3
|
||||||
|
}
|
||||||
|
|
||||||
take_minimum_of_speeds = true
|
take_minimum_of_speeds = true
|
||||||
obey_oneway = true
|
obey_oneway = true
|
||||||
obey_bollards = false
|
obey_bollards = false
|
||||||
@ -158,16 +176,20 @@ function way_function (way)
|
|||||||
local service = way.tags:Find("service")
|
local service = way.tags:Find("service")
|
||||||
local area = way.tags:Find("area")
|
local area = way.tags:Find("area")
|
||||||
local foot = way.tags:Find("foot")
|
local foot = way.tags:Find("foot")
|
||||||
|
local surface = way.tags:Find("surface")
|
||||||
|
|
||||||
-- name
|
-- name
|
||||||
if "" ~= ref then
|
if "" ~= ref and "" ~= name then
|
||||||
way.name = ref
|
way.name = name .. ' / ' .. ref
|
||||||
|
elseif "" ~= ref then
|
||||||
|
way.name = ref
|
||||||
elseif "" ~= name then
|
elseif "" ~= name then
|
||||||
way.name = name
|
way.name = name
|
||||||
else
|
else
|
||||||
way.name = highway -- if no name exists, use way type
|
way.name = "{highway:"..highway.."}" -- if no name exists, use way type
|
||||||
|
-- this encoding scheme is excepted to be a temporary solution
|
||||||
end
|
end
|
||||||
|
|
||||||
-- speed
|
-- speed
|
||||||
if route_speeds[route] then
|
if route_speeds[route] then
|
||||||
-- ferries (doesn't cover routes tagged using relations)
|
-- ferries (doesn't cover routes tagged using relations)
|
||||||
@ -285,6 +307,15 @@ function way_function (way)
|
|||||||
elseif cycleway_right and cycleway_tags[cycleway_right] then
|
elseif cycleway_right and cycleway_tags[cycleway_right] then
|
||||||
way.speed = bicycle_speeds["cycleway"]
|
way.speed = bicycle_speeds["cycleway"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- surfaces
|
||||||
|
if surface then
|
||||||
|
surface_speed = surface_speeds[surface]
|
||||||
|
if surface_speed then
|
||||||
|
way.speed = math.min(way.speed, surface_speed)
|
||||||
|
way.backward_speed = math.min(way.backward_speed, surface_speed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- maxspeed
|
-- maxspeed
|
||||||
-- TODO: maxspeed of backward direction
|
-- TODO: maxspeed of backward direction
|
||||||
|
174
profiles/car.lua
174
profiles/car.lua
@ -11,10 +11,10 @@ service_tag_restricted = { ["parking_aisle"] = true }
|
|||||||
ignore_in_grid = { ["ferry"] = true }
|
ignore_in_grid = { ["ferry"] = true }
|
||||||
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" }
|
||||||
|
|
||||||
speed_profile = {
|
speed_profile = {
|
||||||
["motorway"] = 90,
|
["motorway"] = 90,
|
||||||
["motorway_link"] = 75,
|
["motorway_link"] = 75,
|
||||||
["trunk"] = 85,
|
["trunk"] = 85,
|
||||||
["trunk_link"] = 70,
|
["trunk_link"] = 70,
|
||||||
["primary"] = 65,
|
["primary"] = 65,
|
||||||
["primary_link"] = 60,
|
["primary_link"] = 60,
|
||||||
@ -43,7 +43,7 @@ u_turn_penalty = 20
|
|||||||
-- End of globals
|
-- End of globals
|
||||||
|
|
||||||
function get_exceptions(vector)
|
function get_exceptions(vector)
|
||||||
for i,v in ipairs(restriction_exception_tags) do
|
for i,v in ipairs(restriction_exception_tags) do
|
||||||
vector:Add(v)
|
vector:Add(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -66,13 +66,13 @@ function node_function (node)
|
|||||||
local barrier = node.tags:Find ("barrier")
|
local barrier = node.tags:Find ("barrier")
|
||||||
local access = Access.find_access_tag(node, access_tags_hierachy)
|
local access = Access.find_access_tag(node, access_tags_hierachy)
|
||||||
local traffic_signal = node.tags:Find("highway")
|
local traffic_signal = node.tags:Find("highway")
|
||||||
|
|
||||||
--flag node if it carries a traffic light
|
--flag node if it carries a traffic light
|
||||||
|
|
||||||
if traffic_signal == "traffic_signals" then
|
if traffic_signal == "traffic_signals" then
|
||||||
node.traffic_light = true;
|
node.traffic_light = true;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- parse access and barrier tags
|
-- parse access and barrier tags
|
||||||
if access and access ~= "" then
|
if access and access ~= "" then
|
||||||
if access_tag_blacklist[access] then
|
if access_tag_blacklist[access] then
|
||||||
@ -90,35 +90,40 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function way_function (way)
|
function way_function (way)
|
||||||
-- First, get the properties of each way that we come across
|
-- we dont route over areas
|
||||||
local highway = way.tags:Find("highway")
|
local area = way.tags:Find("area")
|
||||||
local name = way.tags:Find("name")
|
if ignore_areas and ("yes" == area) then
|
||||||
local ref = way.tags:Find("ref")
|
return 0
|
||||||
local junction = way.tags:Find("junction")
|
end
|
||||||
local route = way.tags:Find("route")
|
|
||||||
local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
|
-- check if oneway tag is unsupported
|
||||||
local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward"))
|
local oneway = way.tags:Find("oneway")
|
||||||
local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward"))
|
if "reversible" == oneway then
|
||||||
local barrier = way.tags:Find("barrier")
|
return 0
|
||||||
local oneway = way.tags:Find("oneway")
|
end
|
||||||
local cycleway = way.tags:Find("cycleway")
|
|
||||||
local duration = way.tags:Find("duration")
|
-- Check if we are allowed to access the way
|
||||||
local service = way.tags:Find("service")
|
local access = Access.find_access_tag(way, access_tags_hierachy)
|
||||||
local area = way.tags:Find("area")
|
if access_tag_blacklist[access] then
|
||||||
local access = Access.find_access_tag(way, access_tags_hierachy)
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
-- Second, parse the way according to these properties
|
-- Second, parse the way according to these properties
|
||||||
|
local highway = way.tags:Find("highway")
|
||||||
|
local name = way.tags:Find("name")
|
||||||
|
local ref = way.tags:Find("ref")
|
||||||
|
local junction = way.tags:Find("junction")
|
||||||
|
local route = way.tags:Find("route")
|
||||||
|
local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") )
|
||||||
|
local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward"))
|
||||||
|
local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward"))
|
||||||
|
local barrier = way.tags:Find("barrier")
|
||||||
|
local cycleway = way.tags:Find("cycleway")
|
||||||
|
local duration = way.tags:Find("duration")
|
||||||
|
local service = way.tags:Find("service")
|
||||||
|
|
||||||
if ignore_areas and ("yes" == area) then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if we are allowed to access the way
|
|
||||||
if access_tag_blacklist[access] then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the name that will be used for instructions
|
-- Set the name that will be used for instructions
|
||||||
if "" ~= ref then
|
if "" ~= ref then
|
||||||
way.name = ref
|
way.name = ref
|
||||||
elseif "" ~= name then
|
elseif "" ~= name then
|
||||||
@ -126,87 +131,82 @@ function way_function (way)
|
|||||||
-- else
|
-- else
|
||||||
-- way.name = highway -- if no name exists, use way type
|
-- way.name = highway -- if no name exists, use way type
|
||||||
end
|
end
|
||||||
|
|
||||||
if "roundabout" == junction then
|
if "roundabout" == junction then
|
||||||
way.roundabout = true;
|
way.roundabout = true;
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Handling ferries and piers
|
-- Handling ferries and piers
|
||||||
if (speed_profile[route] ~= nil and speed_profile[route] > 0) then
|
if (speed_profile[route] ~= nil and speed_profile[route] > 0) then
|
||||||
if durationIsValid(duration) then
|
if durationIsValid(duration) then
|
||||||
way.duration = math.max( parseDuration(duration), 1 );
|
way.duration = math.max( parseDuration(duration), 1 );
|
||||||
end
|
end
|
||||||
way.direction = Way.bidirectional
|
way.direction = Way.bidirectional
|
||||||
if speed_profile[route] ~= nil then
|
if speed_profile[route] ~= nil then
|
||||||
highway = route;
|
highway = route;
|
||||||
end
|
end
|
||||||
if tonumber(way.duration) < 0 then
|
if tonumber(way.duration) < 0 then
|
||||||
way.speed = speed_profile[highway]
|
way.speed = speed_profile[highway]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set the avg speed on the way if it is accessible by road class
|
-- Set the avg speed on the way if it is accessible by road class
|
||||||
if (speed_profile[highway] ~= nil and way.speed == -1 ) then
|
if (speed_profile[highway] ~= nil and way.speed == -1 ) then
|
||||||
if maxspeed > speed_profile[highway] then
|
if maxspeed > speed_profile[highway] then
|
||||||
way.speed = maxspeed
|
way.speed = maxspeed
|
||||||
else
|
else
|
||||||
if 0 == maxspeed then
|
if 0 == maxspeed then
|
||||||
maxspeed = math.huge
|
maxspeed = math.huge
|
||||||
end
|
end
|
||||||
way.speed = math.min(speed_profile[highway], maxspeed)
|
way.speed = math.min(speed_profile[highway], maxspeed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set the avg speed on ways that are marked accessible
|
-- Set the avg speed on ways that are marked accessible
|
||||||
if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then
|
if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then
|
||||||
if 0 == maxspeed then
|
if 0 == maxspeed then
|
||||||
maxspeed = math.huge
|
maxspeed = math.huge
|
||||||
end
|
|
||||||
way.speed = math.min(speed_profile["default"], maxspeed)
|
|
||||||
end
|
end
|
||||||
|
way.speed = math.min(speed_profile["default"], maxspeed)
|
||||||
|
end
|
||||||
|
|
||||||
-- Set access restriction flag if access is allowed under certain restrictions only
|
-- Set access restriction flag if access is allowed under certain restrictions only
|
||||||
if access ~= "" and access_tag_restricted[access] then
|
if access ~= "" and access_tag_restricted[access] then
|
||||||
way.is_access_restricted = true
|
way.is_access_restricted = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set access restriction flag if service is allowed under certain restrictions only
|
-- Set access restriction flag if service is allowed under certain restrictions only
|
||||||
if service ~= "" and service_tag_restricted[service] then
|
if service ~= "" and service_tag_restricted[service] then
|
||||||
way.is_access_restricted = true
|
way.is_access_restricted = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set direction according to tags on way
|
-- Set direction according to tags on way
|
||||||
if obey_oneway then
|
way.direction = Way.bidirectional
|
||||||
if oneway == "no" or oneway == "0" or oneway == "false" then
|
if obey_oneway then
|
||||||
way.direction = Way.bidirectional
|
if oneway == "-1" then
|
||||||
elseif oneway == "-1" then
|
|
||||||
way.direction = Way.opposite
|
way.direction = Way.opposite
|
||||||
elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then
|
elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then
|
||||||
way.direction = Way.oneway
|
way.direction = Way.oneway
|
||||||
else
|
|
||||||
way.direction = Way.bidirectional
|
|
||||||
end
|
|
||||||
else
|
|
||||||
way.direction = Way.bidirectional
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Override speed settings if explicit forward/backward maxspeeds are given
|
-- Override speed settings if explicit forward/backward maxspeeds are given
|
||||||
if maxspeed_forward ~= nil and maxspeed_forward > 0 then
|
if maxspeed_forward ~= nil and maxspeed_forward > 0 then
|
||||||
if Way.bidirectional == way.direction then
|
if Way.bidirectional == way.direction then
|
||||||
way.backward_speed = way.speed
|
way.backward_speed = way.speed
|
||||||
end
|
|
||||||
way.speed = maxspeed_forward
|
|
||||||
end
|
|
||||||
if maxspeed_backward ~= nil and maxspeed_backward > 0 then
|
|
||||||
way.backward_speed = maxspeed_backward
|
|
||||||
end
|
end
|
||||||
|
way.speed = maxspeed_forward
|
||||||
|
end
|
||||||
|
if maxspeed_backward ~= nil and maxspeed_backward > 0 then
|
||||||
|
way.backward_speed = maxspeed_backward
|
||||||
|
end
|
||||||
|
|
||||||
-- Override general direction settings of there is a specific one for our mode of travel
|
-- Override general direction settings of there is a specific one for our mode of travel
|
||||||
|
if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
|
||||||
if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then
|
|
||||||
way.ignore_in_grid = true
|
way.ignore_in_grid = true
|
||||||
end
|
end
|
||||||
way.type = 1
|
|
||||||
|
way.type = 1
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ local ipairs = ipairs
|
|||||||
module "Access"
|
module "Access"
|
||||||
|
|
||||||
function find_access_tag(source,access_tags_hierachy)
|
function find_access_tag(source,access_tags_hierachy)
|
||||||
for i,v in ipairs(access_tags_hierachy) do
|
for i,v in ipairs(access_tags_hierachy) do
|
||||||
local tag = source.tags:Find(v)
|
local tag = source.tags:Find(v)
|
||||||
if tag ~= '' then
|
if tag ~= '' then
|
||||||
return tag
|
return tag
|
||||||
|
11
routed.cpp
11
routed.cpp
@ -23,8 +23,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/date_time.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include "Server/DataStructures/QueryObjectsStorage.h"
|
#include "Server/DataStructures/QueryObjectsStorage.h"
|
||||||
#include "Server/ServerConfiguration.h"
|
#include "Server/ServerConfiguration.h"
|
||||||
@ -64,7 +65,7 @@ BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main (int argc, char * argv[0]) {
|
int main (int argc, char * argv[]) {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if(!mlockall(MCL_CURRENT | MCL_FUTURE))
|
if(!mlockall(MCL_CURRENT | MCL_FUTURE))
|
||||||
WARN("Process " << argv[0] << "could not be locked to RAM");
|
WARN("Process " << argv[0] << "could not be locked to RAM");
|
||||||
@ -138,7 +139,11 @@ int main (int argc, char * argv[0]) {
|
|||||||
std::cout << "[server] initiating shutdown" << std::endl;
|
std::cout << "[server] initiating shutdown" << std::endl;
|
||||||
s->Stop();
|
s->Stop();
|
||||||
std::cout << "[server] stopping threads" << std::endl;
|
std::cout << "[server] stopping threads" << std::endl;
|
||||||
t.join();
|
|
||||||
|
if(!t.timed_join(boost::posix_time::seconds(2))) {
|
||||||
|
// INFO("Threads did not finish within 2 seconds. Hard abort!");
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "[server] freeing objects" << std::endl;
|
std::cout << "[server] freeing objects" << std::endl;
|
||||||
delete s;
|
delete s;
|
||||||
delete objects;
|
delete objects;
|
||||||
|
10
typedefs.h
10
typedefs.h
@ -35,16 +35,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#define INFO(x) do {std::cout << "[info " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
|
#define INFO(x) do {std::cout << "[i " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
|
||||||
#define ERR(x) do {std::cerr << "[error " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl; std::exit(-1);} while(0);
|
#define ERR(x) do {std::cerr << "[! " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl; std::exit(-1);} while(0);
|
||||||
#define WARN(x) do {std::cerr << "[warn " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
|
#define WARN(x) do {std::cerr << "[? " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define DEBUG(x)
|
#define DEBUG(x)
|
||||||
#define GUARANTEE(x,y)
|
|
||||||
#else
|
#else
|
||||||
#define DEBUG(x) do {std::cout << "[debug " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
|
#define DEBUG(x) do {std::cout << "[d " << __FILE__ << ":" << __LINE__ << "] " << x << std::endl;} while(0);
|
||||||
#define GUARANTEE(x,y) do { {do{ if(false == (x)) { ERR(y) } } while(0);} } while(0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
|
Loading…
Reference in New Issue
Block a user