Support for 'only_*'-typed turn restrictions.

This commit is contained in:
DennisOSRM 2011-12-02 16:38:10 +01:00
parent f601664620
commit 7be723782a
6 changed files with 62 additions and 35 deletions

View File

@ -144,7 +144,7 @@ private:
try {
_firstEdge.resize( _numNodes + 1 );
} catch(...) {
cerr << "Not enough RAM on machine" << endl;
ERR("Not enough RAM on machine");
return;
}
_firstEdge[0] = 0;
@ -164,7 +164,7 @@ private:
threadData.push_back( new _ThreadData( _numNodes ) );
}
cout << "Scanning for useless shortcuts" << endl;
INFO("Scanning for useless shortcuts");
BuildOutgoingGraph();
#pragma omp parallel for
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
@ -202,7 +202,7 @@ private:
}
}
cout << "Removing edges" << endl;
INFO("Removing edges");
int useful = 0;
for ( int i = 0; i < ( int ) _graph.size(); i++ ) {
if ( !_graph[i].data.forward && !_graph[i].data.backward && _graph[i].data.shortcut )
@ -210,7 +210,7 @@ private:
_graph[useful] = _graph[i];
useful++;
}
cout << "Removed " << _graph.size() - useful << " useless shortcuts" << endl;
INFO("Removed " << _graph.size() - useful << " useless shortcuts");
_graph.resize( useful );
for ( int threadNum = 0; threadNum < maxThreads; ++threadNum ) {
@ -223,6 +223,11 @@ private:
const NodeID node = heapForward->DeleteMin();
const int distance = heapForward->GetKey( node );
if ( distance > *targetDistance ) {
heapForward->DeleteAll();
return;
}
if ( heapBackward->WasInserted( node ) ) {
const int newDistance = heapBackward->GetKey( node ) + distance;
if ( newDistance < *targetDistance ) {
@ -231,10 +236,6 @@ private:
}
}
if ( distance > *targetDistance ) {
heapForward->DeleteAll();
return;
}
for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) {
const NodeID to = _graph[edge].target;
const int edgeWeight = _graph[edge].data.distance;
@ -256,15 +257,15 @@ private:
}
}
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data, std::vector< NodeID >* path = NULL ) {
int _ComputeDistance( NodeID source, NodeID target, _ThreadData * data ) {
data->_heapForward->Clear();
data->_heapBackward->Clear();
//insert source into heap
data->_heapForward->Insert( source, 0, source );
data->_heapBackward->Insert( target, 0, target );
int targetDistance = (std::numeric_limits< int >::max)();
NodeID middle = (std::numeric_limits<NodeID>::max)();
int targetDistance = std::numeric_limits< int >::max();
NodeID middle = std::numeric_limits<NodeID>::max();
while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) {
if ( data->_heapForward->Size() > 0 ) {

View File

@ -99,6 +99,7 @@ void EdgeBasedGraphFactory::Run() {
Percent p(_nodeBasedGraph->GetNumberOfNodes());
int numberOfResolvedRestrictions(0);
int nodeBasedEdgeCounter(0);
NodeID onlyToNode(0);
//Loop over all nodes u. Three nested loop look super-linear, but we are dealing with a number linear in the turns only.
for(_NodeBasedDynamicGraph::NodeIterator u = 0; u < _nodeBasedGraph->GetNumberOfNodes(); ++u ) {
@ -110,29 +111,56 @@ void EdgeBasedGraphFactory::Run() {
++nodeBasedEdgeCounter;
_NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1);
//loop over all reachable edges (v,w)
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
//if (u,v,w) is a forbidden turn, continue
bool isTurnProhibited = false;
if( u != w ) { //only add an edge if turn is not a U-turn
bool isOnlyAllowed(false);
//Check every turn restriction originating from this edge if it is an 'only_*'-turn.
if(restrictionIterator != inputRestrictions.end() && u == restrictionIterator->fromNode) {
std::vector<_Restriction>::iterator secondRestrictionIterator = restrictionIterator;
do {
if( v == secondRestrictionIterator->viaNode && w == secondRestrictionIterator->toNode) {
isTurnProhibited = true;
if(v == secondRestrictionIterator->viaNode) {
if(secondRestrictionIterator->flags.isOnly) {
isOnlyAllowed = true;
onlyToNode = secondRestrictionIterator->toNode;
}
}
++secondRestrictionIterator;
} while(u == secondRestrictionIterator->fromNode);
}
if( !isTurnProhibited ) { //only add an edge if turn is not prohibited
for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) {
_NodeBasedDynamicGraph::NodeIterator w = _nodeBasedGraph->GetTarget(e2);
//if (u,v,w) is a forbidden turn, continue
bool isTurnRestricted(false);
if(isOnlyAllowed && w != onlyToNode) {
// INFO("skipped turn <" << u << "," << v << "," << w << ">, only allowing <" << u << "," << v << "," << onlyToNode << ">");
continue;
}
if( u != w ) { //only add an edge if turn is not a U-turn
if(restrictionIterator != inputRestrictions.end() && u == restrictionIterator->fromNode) {
std::vector<_Restriction>::iterator secondRestrictionIterator = restrictionIterator;
do {
if(v == secondRestrictionIterator->viaNode) {
if(w == secondRestrictionIterator->toNode) {
isTurnRestricted = true;
}
}
++secondRestrictionIterator;
} while(u == secondRestrictionIterator->fromNode);
}
if( !isTurnRestricted || (isOnlyAllowed && w == onlyToNode) ) { //only add an edge if turn is not prohibited
if(isOnlyAllowed && w == onlyToNode) {
// INFO("Adding 'only_*'-turn <" << u << "," << v << "," << w << ">");
} else if(isOnlyAllowed && w != onlyToNode) {
assert(false);
}
//new costs for edge based edge (e1, e2) = cost (e1) + tc(e1,e2)
const _NodeBasedDynamicGraph::NodeIterator edgeBasedSource = _nodeBasedGraph->GetEdgeData(e1).edgeBasedNodeID;
// INFO("edgeBasedSource: " << edgeBasedSource);
if(edgeBasedSource > _nodeBasedGraph->GetNumberOfEdges()) {
ERR("edgeBasedTarget" << edgeBasedSource << ">" << _nodeBasedGraph->GetNumberOfEdges());
}
const _NodeBasedDynamicGraph::NodeIterator edgeBasedTarget = _nodeBasedGraph->GetEdgeData(e2).edgeBasedNodeID;
// INFO("edgeBasedTarget: " << edgeBasedTarget);
if(edgeBasedTarget > _nodeBasedGraph->GetNumberOfEdges()) {
ERR("edgeBasedTarget" << edgeBasedTarget << ">" << _nodeBasedGraph->GetNumberOfEdges());
}
@ -145,7 +173,6 @@ void EdgeBasedGraphFactory::Run() {
short turnInstruction = AnalyzeTurn(u, v, w);
//create edge-based graph edge
//EdgeBasedEdge(NodeID s, NodeID t, NodeID v, unsigned n1, EdgeWeight w, bool f, bool b, short ty)
EdgeBasedEdge newEdge(edgeBasedSource, edgeBasedTarget, v, nameID, distance, true, false, turnInstruction);
edgeBasedEdges.push_back(newEdge);
EdgeBasedNode currentNode;

View File

@ -121,7 +121,7 @@ public:
//Is the highway tag listed as usable way?
if(0 < settings[highway]) {
if(0 != maxspeed)
if(0 < maxspeed)
w.speed = maxspeed;
else
w.speed = settings[highway];
@ -154,7 +154,6 @@ public:
//Is the route tag listed as usable way in the profile?
if(settings[route] > 0 || settings[man_made] > 0) {
w.useful = true;
w.direction = _Way::oneway;
w.speed = settings[route];
w.direction = _Way::bidirectional;
}
@ -178,7 +177,7 @@ public:
return true;
}
if(w.id == UINT_MAX) {
WARN("found way with unknown type" << w.id);
WARN("found way with unknown type: " << w.id);
return true;
}

View File

@ -177,10 +177,10 @@ struct _RawRestrictionContainer {
_Restriction restriction;
EdgeID fromWay;
EdgeID toWay;
unsigned viaWay;
unsigned viaNode;
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaWay(vw) { restriction.viaNode = vn;}
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaWay(UINT_MAX) { restriction.flags.isOnly = isOnly;}
_RawRestrictionContainer(EdgeID f, EdgeID t, NodeID vn, unsigned vw) : fromWay(f), toWay(t), viaNode(vw) { restriction.viaNode = vn;}
_RawRestrictionContainer(bool isOnly = false) : fromWay(UINT_MAX), toWay(UINT_MAX), viaNode(UINT_MAX) { restriction.flags.isOnly = isOnly;}
static _RawRestrictionContainer min_value() {
return _RawRestrictionContainer((numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)(), (numeric_limits<unsigned>::min)());
@ -233,7 +233,7 @@ struct _WayIDStartAndEndEdge {
}
};
struct CmpWayStartAndEnd : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
struct CmpWayByID : public std::binary_function<_WayIDStartAndEndEdge, _WayIDStartAndEndEdge, bool> {
typedef _WayIDStartAndEndEdge value_type;
bool operator () (const _WayIDStartAndEndEdge & a, const _WayIDStartAndEndEdge & b) const {
return a.wayID < b.wayID;

View File

@ -270,9 +270,9 @@ private:
if("from" == role || "to" == role) //Only via should be a node
continue;
assert("via" == role);
if(UINT_MAX != currentRestrictionContainer.viaWay)
currentRestrictionContainer.viaWay = UINT_MAX;
assert(UINT_MAX == currentRestrictionContainer.viaWay);
if(UINT_MAX != currentRestrictionContainer.viaNode)
currentRestrictionContainer.viaNode = UINT_MAX;
assert(UINT_MAX == currentRestrictionContainer.viaNode);
currentRestrictionContainer.restriction.viaNode = lastRef;
break;
case 1: //way
@ -285,7 +285,7 @@ private:
}
if ("via" == role) {
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
currentRestrictionContainer.viaWay = lastRef;
currentRestrictionContainer.viaNode = lastRef;
}
break;
case 2: //relation, not used. relations relating to relations are evil.
@ -315,7 +315,6 @@ private:
for(int i = 0; i < threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i++) {
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
_Way w;
w.id = inputWay.id();
unsigned pathNode(0);
for(int i = 0; i < inputWay.refs_size(); i++) {
pathNode += inputWay.refs(i);

View File

@ -208,7 +208,7 @@ int main (int argc, char *argv[]) {
time = get_timestamp();
cout << "[extractor] Sorting used ways ... " << flush;
stxxl::sort(externalMemory.wayStartEndVector.begin(), externalMemory.wayStartEndVector.end(), CmpWayStartAndEnd(), memory_to_use);
stxxl::sort(externalMemory.wayStartEndVector.begin(), externalMemory.wayStartEndVector.end(), CmpWayByID(), memory_to_use);
cout << "ok, after " << get_timestamp() - time << "s" << endl;
cout << "[extractor] Sorting restrctns. by from... " << flush;
@ -255,8 +255,7 @@ int main (int argc, char *argv[]) {
cout << "[extractor] Fixing restriction ends ... " << flush;
restrictionsIT = externalMemory.restrictionsVector.begin();
wayStartAndEndEdgeIT = externalMemory.wayStartEndVector.begin();
while(wayStartAndEndEdgeIT != externalMemory.wayStartEndVector.end() &&
restrictionsIT != externalMemory.restrictionsVector.end()) {
while(wayStartAndEndEdgeIT != externalMemory.wayStartEndVector.end() && restrictionsIT != externalMemory.restrictionsVector.end()) {
if(wayStartAndEndEdgeIT->wayID < restrictionsIT->toWay){
++wayStartAndEndEdgeIT;
continue;
@ -278,11 +277,13 @@ int main (int argc, char *argv[]) {
if(UINT_MAX != restrictionsIT->restriction.fromNode && UINT_MAX != restrictionsIT->restriction.toNode) {
++usableRestrictionsCounter;
} else {
INFO("Restriction from: " << restrictionsIT->restriction.fromNode << ", to: " << restrictionsIT->restriction.toNode);
}
++restrictionsIT;
}
cout << "ok, after " << get_timestamp() - time << "s" << endl;
INFO("usable restrictions: " << usableRestrictionsCounter);
//serialize restrictions
ofstream restrictionsOutstream;
restrictionsOutstream.open(restrictionsFileName.c_str(), ios::binary);