From 7be723782a23bb3e122fa4cfecc0fd00fa3dcf4f Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Fri, 2 Dec 2011 16:38:10 +0100 Subject: [PATCH] Support for 'only_*'-typed turn restrictions. --- Contractor/ContractionCleanup.h | 25 +++++++++-------- Contractor/EdgeBasedGraphFactory.cpp | 41 +++++++++++++++++++++++----- DataStructures/ExtractorCallBacks.h | 5 ++-- DataStructures/ExtractorStructs.h | 8 +++--- DataStructures/PBFParser.h | 9 +++--- extractor.cpp | 9 +++--- 6 files changed, 62 insertions(+), 35 deletions(-) diff --git a/Contractor/ContractionCleanup.h b/Contractor/ContractionCleanup.h index bc9f9c4e4..e2b75e1ae 100644 --- a/Contractor/ContractionCleanup.h +++ b/Contractor/ContractionCleanup.h @@ -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,11 +236,7 @@ private: } } - if ( distance > *targetDistance ) { - heapForward->DeleteAll(); - return; - } - for ( int edge = _firstEdge[node], endEdges = _firstEdge[node + 1]; edge != endEdges; ++edge ) { + 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; assert( edgeWeight > 0 ); @@ -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::max)(); + int targetDistance = std::numeric_limits< int >::max(); + NodeID middle = std::numeric_limits::max(); while ( data->_heapForward->Size() + data->_heapBackward->Size() > 0 ) { if ( data->_heapForward->Size() > 0 ) { diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index b461ddf24..517e1337a 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -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) + 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) { + if(secondRestrictionIterator->flags.isOnly) { + isOnlyAllowed = true; + onlyToNode = secondRestrictionIterator->toNode; + } + } + ++secondRestrictionIterator; + } while(u == secondRestrictionIterator->fromNode); + } + 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; + 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 && w == secondRestrictionIterator->toNode) { - isTurnProhibited = true; + if(v == secondRestrictionIterator->viaNode) { + if(w == secondRestrictionIterator->toNode) { + isTurnRestricted = true; + } } ++secondRestrictionIterator; } while(u == secondRestrictionIterator->fromNode); } - if( !isTurnProhibited ) { //only add an edge if turn is not prohibited + + 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; diff --git a/DataStructures/ExtractorCallBacks.h b/DataStructures/ExtractorCallBacks.h index 67c96689a..0face8d56 100644 --- a/DataStructures/ExtractorCallBacks.h +++ b/DataStructures/ExtractorCallBacks.h @@ -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; } diff --git a/DataStructures/ExtractorStructs.h b/DataStructures/ExtractorStructs.h index 0f5ead963..0cbd7d7f4 100644 --- a/DataStructures/ExtractorStructs.h +++ b/DataStructures/ExtractorStructs.h @@ -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::min)(), (numeric_limits::min)(), (numeric_limits::min)(), (numeric_limits::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; diff --git a/DataStructures/PBFParser.h b/DataStructures/PBFParser.h index a211cb6e9..c76ba3ef7 100644 --- a/DataStructures/PBFParser.h +++ b/DataStructures/PBFParser.h @@ -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); diff --git a/extractor.cpp b/extractor.cpp index a9e098c16..a709016da 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -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);