Merge branch 'develop' of https://github.com/DennisOSRM/Project-OSRM into develop
This commit is contained in:
commit
b43a51f912
@ -12,7 +12,7 @@ file(GLOB PrepareGlob Contractor/*.cpp)
|
|||||||
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
|
set(PrepareSources createHierarchy.cpp ${PrepareGlob})
|
||||||
add_executable(osrm-prepare ${PrepareSources})
|
add_executable(osrm-prepare ${PrepareSources})
|
||||||
|
|
||||||
file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp)
|
file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp DataStructures/SearchEngine*.cpp)
|
||||||
set(RoutedSources routed.cpp ${RoutedGlob})
|
set(RoutedSources routed.cpp ${RoutedGlob})
|
||||||
add_executable(osrm-routed ${RoutedSources})
|
add_executable(osrm-routed ${RoutedSources})
|
||||||
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED)
|
||||||
|
@ -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,7 +89,10 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,20 @@ 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/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 +49,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 +82,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 +93,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 {
|
||||||
@ -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 {
|
||||||
|
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();
|
||||||
|
};
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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{
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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 <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) {
|
||||||
|
@ -18,25 +18,7 @@ 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 <lua.h>
|
|
||||||
#include <lauxlib.h>
|
|
||||||
#include <lualib.h>
|
|
||||||
}
|
|
||||||
#include <luabind/luabind.hpp>
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <istream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Algorithms/IteratorBasedCRC32.h"
|
#include "Algorithms/IteratorBasedCRC32.h"
|
||||||
#include "Util/OpenMPWrapper.h"
|
|
||||||
#include "typedefs.h"
|
|
||||||
#include "Contractor/Contractor.h"
|
#include "Contractor/Contractor.h"
|
||||||
#include "Contractor/EdgeBasedGraphFactory.h"
|
#include "Contractor/EdgeBasedGraphFactory.h"
|
||||||
#include "DataStructures/BinaryHeap.h"
|
#include "DataStructures/BinaryHeap.h"
|
||||||
@ -47,7 +29,20 @@ extern "C" {
|
|||||||
#include "Util/GraphLoader.h"
|
#include "Util/GraphLoader.h"
|
||||||
#include "Util/InputFileUtil.h"
|
#include "Util/InputFileUtil.h"
|
||||||
#include "Util/LuaUtil.h"
|
#include "Util/LuaUtil.h"
|
||||||
|
#include "Util/OpenMPWrapper.h"
|
||||||
#include "Util/StringUtil.h"
|
#include "Util/StringUtil.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include <luabind/luabind.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <istream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
typedef QueryEdge::EdgeData EdgeData;
|
typedef QueryEdge::EdgeData EdgeData;
|
||||||
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
||||||
@ -61,212 +56,216 @@ 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 ramIndexOut(argv[1]); ramIndexOut += ".ramIndex";
|
||||||
//Serialize numberOfNodes, nodes
|
std::string fileIndexOut(argv[1]); fileIndexOut += ".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);
|
||||||
|
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 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!");
|
||||||
}
|
}
|
||||||
|
@ -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 |
|
||||||
|
|
||||||
|
|
||||||
|
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