diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 495b13147..b9059ca62 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -157,11 +157,13 @@ public: forwardEdge.data.distance = backwardEdge.data.distance = std::numeric_limits< int >::max(); //remove parallel edges while ( i < edges.size() && edges[i].source == source && edges[i].target == target ) { - if ( edges[i].data.forward ) + if ( edges[i].data.forward) { forwardEdge.data.distance = std::min( edges[i].data.distance, forwardEdge.data.distance ); - if ( edges[i].data.backward ) + } + if ( edges[i].data.backward) { backwardEdge.data.distance = std::min( edges[i].data.distance, backwardEdge.data.distance ); - i++; + } + ++i; } //merge edges (s,t) and (t,s) into bidirectional edge if ( forwardEdge.data.distance == backwardEdge.data.distance ) { @@ -242,7 +244,7 @@ public: nodePriority[x] = _Evaluate( data, &nodeData[x], x ); } } - std::cout << "ok" << std::endl << "preprocessing ..." << std::flush; + std::cout << "ok" << std::endl << "preprocessing " << numberOfNodes << " nodes ..." << std::flush; bool flushedContractor = false; while ( numberOfContractedNodes < numberOfNodes ) { diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index e484a25e6..d7ea8e6e0 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -61,9 +61,9 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectorisForward(); edge.data.backward = i->isBackward(); } - if(edge.source == edge.target) - continue; - + if(edge.source == edge.target) { + continue; + } edge.data.distance = (std::max)((int)i->weight(), 1 ); assert( edge.data.distance > 0 ); edge.data.shortcut = false; @@ -73,6 +73,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectortype(); edge.data.isAccessRestricted = i->isAccessRestricted(); edge.data.edgeBasedNodeID = edges.size(); + edge.data.contraFlow = i->isContraFlow(); edges.push_back( edge ); if( edge.data.backward ) { std::swap( edge.source, edge.target ); @@ -107,7 +108,7 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn(const NodeID u, const RestrictionMap::const_iterator restrIter = _restrictionMap.find(restrictionSource); if (restrIter != _restrictionMap.end()) { unsigned index = restrIter->second; - BOOST_FOREACH(RestrictionSource restrictionTarget, _restrictionBucketVector.at(index)) { + BOOST_FOREACH(const RestrictionSource & restrictionTarget, _restrictionBucketVector.at(index)) { if(restrictionTarget.second) { return restrictionTarget.first; } @@ -239,6 +240,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) { ++nodeBasedEdgeCounter; _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1); + bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end()); //EdgeWeight heightPenalty = ComputeHeightPenalty(u, v); NodeID onlyToNode = CheckForEmanatingIsOnlyTurn(u, v); for(_NodeBasedDynamicGraph::EdgeIterator e2 = _nodeBasedGraph->BeginEdges(v); e2 < _nodeBasedGraph->EndEdges(v); ++e2) { @@ -248,7 +250,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { ++numberOfSkippedTurns; continue; } - bool isBollardNode = (_barrierNodes.find(v) != _barrierNodes.end()); + if(u == w && 1 != _nodeBasedGraph->GetOutDegree(v) ) { continue; } @@ -291,7 +293,6 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { originalEdgeData.clear(); } ++numberOfOriginalEdges; - ++nodeBasedEdgeCounter; edgeBasedEdges.push_back(newEdge); } else { ++numberOfSkippedTurns; @@ -316,6 +317,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename) { // std::vector(edgeBasedNodes).swap(edgeBasedNodes); // INFO("size: " << edgeBasedNodes.size() << ", cap: " << edgeBasedNodes.capacity()); INFO("Node-based graph contains " << nodeBasedEdgeCounter << " edges"); + INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges"); // INFO("Edge-based graph contains " << edgeBasedEdges.size() << " edges, blowup is " << 2*((double)edgeBasedEdges.size()/(double)nodeBasedEdgeCounter)); INFO("Edge-based graph skipped " << numberOfSkippedTurns << " turns, defined by " << numberOfTurnRestrictions << " restrictions."); INFO("Generated " << edgeBasedNodes.size() << " edge based nodes"); @@ -332,6 +334,13 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID _NodeBasedDynamicGraph::EdgeData & data1 = _nodeBasedGraph->GetEdgeData(edge1); _NodeBasedDynamicGraph::EdgeData & data2 = _nodeBasedGraph->GetEdgeData(edge2); + if(!data1.contraFlow && data2.contraFlow) { + return TurnInstructions.EnterAgainstAllowedDirection; + } + if(data1.contraFlow && !data2.contraFlow) { + return TurnInstructions.LeaveAgainstAllowedDirection; + } + //roundabouts need to be handled explicitely if(data1.roundabout && data2.roundabout) { //Is a turn possible? If yes, we stay on the roundabout! @@ -353,10 +362,12 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID } //If street names stay the same and if we are certain that it is not a roundabout, we skip it. - if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) + if( (data1.nameID == data2.nameID) && (0 != data1.nameID)) { return TurnInstructions.NoTurn; - if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) + } + if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) { return TurnInstructions.NoTurn; + } double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); return TurnInstructions.GetTurnDirectionOfInstruction(angle); diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 12c6c198b..45ac0ad39 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -49,34 +50,7 @@ #include "../DataStructures/TurnInstructions.h" #include "../Util/BaseConfiguration.h" -class EdgeBasedGraphFactory { -private: - struct _NodeBasedEdgeData { - int distance; - unsigned edgeBasedNodeID; - unsigned nameID; - short type; - bool isAccessRestricted; - bool shortcut:1; - bool forward:1; - bool backward:1; - bool roundabout:1; - bool ignoreInGrid:1; - }; - - struct _EdgeBasedEdgeData { - int distance; - unsigned via; - unsigned nameID; - bool forward; - bool backward; - TurnInstruction turnInstruction; - }; - - typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; - typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge; - std::vector inputNodeInfoList; - unsigned numberOfTurnRestrictions; +class EdgeBasedGraphFactory : boost::noncopyable { public: struct EdgeBasedNode { bool operator<(const EdgeBasedNode & other) const { @@ -96,13 +70,41 @@ public: bool ignoreInGrid:1; }; - struct SpeedProfileProperties{ SpeedProfileProperties() : trafficSignalPenalty(0), uTurnPenalty(0) {} int trafficSignalPenalty; int uTurnPenalty; } speedProfile; + private: + struct _NodeBasedEdgeData { + int distance; + unsigned edgeBasedNodeID; + unsigned nameID; + short type; + bool isAccessRestricted; + bool shortcut:1; + bool forward:1; + bool backward:1; + bool roundabout:1; + bool ignoreInGrid:1; + bool contraFlow; + }; + + struct _EdgeBasedEdgeData { + int distance; + unsigned via; + unsigned nameID; + bool forward; + bool backward; + TurnInstruction turnInstruction; + }; + + typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; + typedef _NodeBasedDynamicGraph::InputEdge _NodeBasedEdge; + std::vector inputNodeInfoList; + unsigned numberOfTurnRestrictions; + boost::shared_ptr<_NodeBasedDynamicGraph> _nodeBasedGraph; boost::unordered_set _barrierNodes; boost::unordered_set _trafficLights; @@ -114,7 +116,6 @@ private: std::vector _restrictionBucketVector; RestrictionMap _restrictionMap; - DeallocatingVector edgeBasedEdges; DeallocatingVector edgeBasedNodes; std::vector originalEdgeData; diff --git a/DataStructures/DeallocatingVector.h b/DataStructures/DeallocatingVector.h index 89502f7d4..d3c19d170 100644 --- a/DataStructures/DeallocatingVector.h +++ b/DataStructures/DeallocatingVector.h @@ -302,6 +302,18 @@ public: size_t _index = index % bucketSizeC; return (mBucketList[_bucket][_index]); } + + inline ElementT & back() { + size_t _bucket = mCurrentSize / bucketSizeC; + size_t _index = mCurrentSize % bucketSizeC; + return (mBucketList[_bucket][_index]); + } + + const inline ElementT & back() const { + size_t _bucket = mCurrentSize / bucketSizeC; + size_t _index = mCurrentSize % bucketSizeC; + return (mBucketList[_bucket][_index]); + } }; #endif /* DEALLOCATINGVECTOR_H_ */ diff --git a/DataStructures/DynamicGraph.h b/DataStructures/DynamicGraph.h index c2a54059d..64bfa6087 100644 --- a/DataStructures/DynamicGraph.h +++ b/DataStructures/DynamicGraph.h @@ -72,6 +72,7 @@ class DynamicGraph { m_nodes[node].edges = edge - lastEdge; position += m_nodes[node].edges; } + m_nodes.back().firstEdge = position; m_edges.reserve( position * 1.1 ); m_edges.resize( position ); edge = 0; diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index a90cd474d..1b5966c40 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -40,12 +40,8 @@ public: return (source() < e.source()); } - /** Default constructor. target and weight are set to 0.*/ - NodeBasedEdge() : - _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false) { assert(false); } //shall not be used. - - explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar) : - _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar) { if(ty < 0) {ERR("Type: " << ty);}; } + explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, short ty, bool ra, bool ig, bool ar, bool cf) : + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf) { if(ty < 0) {ERR("Type: " << ty);}; } NodeID target() const {return _target; } NodeID source() const {return _source; } @@ -59,6 +55,7 @@ public: bool isRoundabout() const { return _roundabout; } bool ignoreInGrid() const { return _ignoreInGrid; } bool isAccessRestricted() const { return _accessRestricted; } + bool isContraFlow() const { return _contraFlow; } NodeID _source; NodeID _target; @@ -70,6 +67,13 @@ public: bool _roundabout; bool _ignoreInGrid; bool _accessRestricted; + bool _contraFlow; + +private: + /** Default constructor. target and weight are set to 0.*/ + NodeBasedEdge() : + _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false) { assert(false); } //shall not be used. + }; class EdgeBasedEdge { diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 4c156ea61..22cb4e2d4 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -221,7 +221,7 @@ public: // } // INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location); - double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0); + const double ratio = (foundNode ? std::min(1., ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)) : 0); resultNode.location.lat = round(100000.*(y2lat(static_cast(resultNode.location.lat)/100000.))); // INFO("Length of vector: " << ApproximateDistance(smallestEdge.startCoord, resultNode.location)/ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)); //Hack to fix rounding errors and wandering via nodes. @@ -232,12 +232,13 @@ public: resultNode.weight1 *= ratio; if(INT_MAX != resultNode.weight2) { - resultNode.weight2 -= resultNode.weight1; + resultNode.weight2 *= (1.-ratio); } resultNode.ratio = ratio; -// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio); // INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord); -// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no") << "\n--"); +// INFO("selected node: " << resultNode.edgeBasedNode << ", bidirected: " << (resultNode.isBidirected() ? "yes" : "no")); +// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2 << ", ratio: " << ratio); + // INFO("distance to input coordinate: " << ApproximateDistance(location, resultNode.location) << "\n--"); // double time2 = get_timestamp(); // INFO("NN-Lookup in " << 1000*(time2-time1) << "ms"); return foundNode; diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index 2e709831d..3284d9bbe 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -21,12 +21,12 @@ #ifndef TURNINSTRUCTIONS_H_ #define TURNINSTRUCTIONS_H_ -#include +#include typedef unsigned char TurnInstruction; //This is a hack until c++0x is available enough to use scoped enums -struct TurnInstructionsClass { +struct TurnInstructionsClass : boost::noncopyable { const static TurnInstruction NoTurn = 0; //Give no instruction at all const static TurnInstruction GoStraight = 1; //Tell user to go straight! @@ -44,48 +44,14 @@ struct TurnInstructionsClass { const static TurnInstruction StayOnRoundAbout = 13; const static TurnInstruction StartAtEndOfStreet = 14; const static TurnInstruction ReachedYourDestination = 15; + const static TurnInstruction EnterAgainstAllowedDirection = 16; + const static TurnInstruction LeaveAgainstAllowedDirection = 17; const static TurnInstruction AccessRestrictionFlag = 128; const static TurnInstruction InverseAccessRestrictionFlag = 0x7f; // ~128 does not work without a warning. const static int AccessRestrictionPenalty = 1 << 15; //unrelated to the bit set in the restriction flag -// std::string TurnStrings[16]; -// std::string Ordinals[12]; - - //This is a hack until c++0x is available enough to use initializer lists. -// TurnInstructionsClass(){ -// TurnStrings [0] = ""; -// TurnStrings [1] = "Continue"; -// TurnStrings [2] = "Turn slight right"; -// TurnStrings [3] = "Turn right"; -// TurnStrings [4] = "Turn sharp right"; -// TurnStrings [5] = "U-Turn"; -// TurnStrings [6] = "Turn sharp left"; -// TurnStrings [7] = "Turn left"; -// TurnStrings [8] = "Turn slight left"; -// TurnStrings [9] = "Reach via point"; -// TurnStrings[10] = "Head"; -// TurnStrings[11] = "Enter roundabout"; -// TurnStrings[12] = "Leave roundabout"; -// TurnStrings[13] = "Stay on roundabout"; -// TurnStrings[14] = "Start"; -// TurnStrings[15] = "You have reached your destination"; -// -// Ordinals[0] = "zeroth"; -// Ordinals[1] = "first"; -// Ordinals[2] = "second"; -// Ordinals[3] = "third"; -// Ordinals[4] = "fourth"; -// Ordinals[5] = "fifth"; -// Ordinals[6] = "sixth"; -// Ordinals[7] = "seventh"; -// Ordinals[8] = "eighth"; -// Ordinals[9] = "nineth"; -// Ordinals[10] = "tenth"; -// Ordinals[11] = "one of the too many"; -// }; - static inline TurnInstruction GetTurnDirectionOfInstruction( const double angle ) { if(angle >= 23 && angle < 67) { return TurnSharpRight; diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index 93a0fd674..b2476bc86 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -231,17 +231,17 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->target, sizeof(unsigned)); fout.write((char*)&intDist, sizeof(int)); switch(edgeIT->direction) { - case _Way::notSure: + case ExtractionWay::notSure: fout.write((char*)&zero, sizeof(short)); break; - case _Way::oneway: + case ExtractionWay::oneway: fout.write((char*)&one, sizeof(short)); break; - case _Way::bidirectional: + case ExtractionWay::bidirectional: fout.write((char*)&zero, sizeof(short)); break; - case _Way::opposite: + case ExtractionWay::opposite: fout.write((char*)&one, sizeof(short)); break; default: @@ -256,6 +256,7 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const fout.write((char*)&edgeIT->isRoundabout, sizeof(bool)); fout.write((char*)&edgeIT->ignoreInGrid, sizeof(bool)); fout.write((char*)&edgeIT->isAccessRestricted, sizeof(bool)); + fout.write((char*)&edgeIT->isContraFlow, sizeof(bool)); } ++usedEdgeCounter; ++edgeIT; diff --git a/Extractor/ExtractionContainers.h b/Extractor/ExtractionContainers.h index 7e8a1d7be..abf718d5f 100644 --- a/Extractor/ExtractionContainers.h +++ b/Extractor/ExtractionContainers.h @@ -31,7 +31,7 @@ class ExtractionContainers { public: typedef stxxl::vector STXXLNodeIDVector; typedef stxxl::vector<_Node> STXXLNodeVector; - typedef stxxl::vector<_Edge> STXXLEdgeVector; + typedef stxxl::vector STXXLEdgeVector; typedef stxxl::vector STXXLStringVector; typedef stxxl::vector<_RawRestrictionContainer> STXXLRestrictionsVector; typedef stxxl::vector<_WayIDStartAndEndEdge> STXXLWayIDStartEndVector; diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index 1702ec0d5..5da2bce4f 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -64,46 +64,84 @@ bool ExtractorCallbacks::restrictionFunction(_RawRestrictionContainer &r) { } /** warning: caller needs to take care of synchronization! */ -bool ExtractorCallbacks::wayFunction(_Way &w) { - /*** Store name of way and split it into edge segments ***/ - - if ( (0 < w.speed) || (0 < w.duration) ) { //Only true if the way is specified by the speed profile +bool ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { + if ( parsed_way.speed > 0 || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile + if(parsed_way.id == UINT_MAX){ + WARN("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); + return true; + } //Get the unique identifier for the street name - const StringMap::const_iterator strit = stringMap->find(w.name); - if(strit == stringMap->end()) { - w.nameID = externalMemory->nameVector.size(); - externalMemory->nameVector.push_back(w.name); - stringMap->insert(StringMap::value_type(w.name, w.nameID)); + const StringMap::const_iterator string_map_iterator = stringMap->find(parsed_way.name); + if(string_map_iterator == stringMap->end()) { + parsed_way.nameID = externalMemory->nameVector.size(); + externalMemory->nameVector.push_back(parsed_way.name); + stringMap->insert(StringMap::value_type(parsed_way.name, parsed_way.nameID)); } else { - w.nameID = strit->second; + parsed_way.nameID = string_map_iterator->second; } - if(w.duration > 0) { - //TODO: iterate all way segments and set duration corresponding to the length of each segment - w.speed = w.duration/(w.path.size()-1); + if(parsed_way.duration > 0) { + //TODO: iterate all way segments and set duration corresponding to the length of each segment + parsed_way.speed = parsed_way.duration/(parsed_way.path.size()-1); } - if(fabs(-1. - w.speed) < FLT_EPSILON){ - WARN("found way with bogus speed, id: " << w.id); + if(fabs(-1. - parsed_way.speed) < FLT_EPSILON){ + WARN("found way with bogus speed, id: " << parsed_way.id); return true; } - if(w.id == UINT_MAX) { - WARN("found way with unknown type: " << w.id); + if(parsed_way.id == UINT_MAX) { + WARN("found way with unknown type: " << parsed_way.id); return true; } - if ( w.direction == _Way::opposite ){ - std::reverse( w.path.begin(), w.path.end() ); + if ( parsed_way.direction == ExtractionWay::opposite ){ + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + parsed_way.direction = ExtractionWay::oneway; } - for(std::vector< NodeID >::size_type n = 0; n < w.path.size()-1; ++n) { - externalMemory->allEdges.push_back(_Edge(w.path[n], w.path[n+1], w.type, w.direction, w.speed, w.nameID, w.roundabout, w.ignoreInGrid, (w.duration > 0), w.isAccessRestricted)); - externalMemory->usedNodeIDs.push_back(w.path[n]); + bool split_bidirectional_edge = (parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed); + + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + InternalExtractorEdge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + (split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction), + parsed_way.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + (0 < parsed_way.duration), + parsed_way.isAccessRestricted + ) + ); + externalMemory->usedNodeIDs.push_back(parsed_way.path[n]); } - externalMemory->usedNodeIDs.push_back(w.path.back()); + externalMemory->usedNodeIDs.push_back(parsed_way.path.back()); //The following information is needed to identify start and end segments of restrictions - externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(w.id, w.path[0], w.path[1], w.path[w.path.size()-2], w.path[w.path.size()-1])); + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); + + if ( split_bidirectional_edge) { //Only true if the way should be split + std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->allEdges.push_back( + InternalExtractorEdge(parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + ExtractionWay::oneway, + parsed_way.backward_speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + (0 < parsed_way.duration), + parsed_way.isAccessRestricted, + (ExtractionWay::oneway == parsed_way.direction) + ) + ); + } + externalMemory->wayStartEndVector.push_back(_WayIDStartAndEndEdge(parsed_way.id, parsed_way.path[0], parsed_way.path[1], parsed_way.path[parsed_way.path.size()-2], parsed_way.path.back())); + } } return true; } diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h index 70f812ec2..3ddbbe841 100644 --- a/Extractor/ExtractorCallbacks.h +++ b/Extractor/ExtractorCallbacks.h @@ -50,7 +50,7 @@ public: bool restrictionFunction(_RawRestrictionContainer &r); /** warning: caller needs to take care of synchronization! */ - bool wayFunction(_Way &w); + bool wayFunction(ExtractionWay &w); }; diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index 5ea22cbd9..644408ca4 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -40,8 +40,8 @@ or see http://www.gnu.org/licenses/agpl.txt. typedef boost::unordered_map StringMap; typedef boost::unordered_map > StringToIntPairMap; -struct _Way { - _Way() { +struct ExtractionWay { + ExtractionWay() { Clear(); } @@ -50,8 +50,9 @@ struct _Way { nameID = UINT_MAX; path.clear(); keyVals.EraseAll(); - direction = _Way::notSure; + direction = ExtractionWay::notSure; speed = -1; + backward_speed = -1; duration = -1; type = -1; access = true; @@ -67,6 +68,7 @@ struct _Way { unsigned nameID; std::string name; double speed; + double backward_speed; double duration; short type; bool access; @@ -77,19 +79,22 @@ struct _Way { HashTable keyVals; }; -struct _Relation { - _Relation() : type(unknown){} +struct ExtractorRelation { + ExtractorRelation() : type(unknown){} enum { unknown = 0, ferry, turnRestriction } type; HashTable keyVals; }; -struct _Edge { - _Edge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {}; - _Edge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) { } - _Edge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar) { +struct InternalExtractorEdge { + InternalExtractorEdge() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) {}; + InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp): start(s), target(t), type(tp), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false) { } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false) { + assert(0 <= type); + } + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(icf) { assert(0 <= type); } NodeID start; @@ -102,19 +107,21 @@ struct _Edge { bool ignoreInGrid; bool isDurationSet; bool isAccessRestricted; + bool isContraFlow; _Coordinate startCoord; _Coordinate targetCoord; - static _Edge min_value() { - return _Edge(0,0); + static InternalExtractorEdge min_value() { + return InternalExtractorEdge(0,0); } - static _Edge max_value() { - return _Edge((std::numeric_limits::max)(), (std::numeric_limits::max)()); + static InternalExtractorEdge max_value() { + return InternalExtractorEdge((std::numeric_limits::max)(), (std::numeric_limits::max)()); } - }; + + struct _WayIDStartAndEndEdge { unsigned wayID; NodeID firstStart; @@ -171,34 +178,29 @@ struct CmpNodeByID : public std::binary_function<_Node, _Node, bool> { } }; -struct CmpEdgeByStartID : public std::binary_function<_Edge, _Edge, bool> -{ - typedef _Edge value_type; - bool operator () (const _Edge & a, const _Edge & b) const { +struct CmpEdgeByStartID : public std::binary_function { + typedef InternalExtractorEdge value_type; + bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const { return a.start < b.start; } value_type max_value() { - return _Edge::max_value(); + return InternalExtractorEdge::max_value(); } value_type min_value() { - return _Edge::min_value(); + return InternalExtractorEdge::min_value(); } }; -struct CmpEdgeByTargetID : public std::binary_function<_Edge, _Edge, bool> -{ - typedef _Edge value_type; - bool operator () (const _Edge & a, const _Edge & b) const - { +struct CmpEdgeByTargetID : public std::binary_function { + typedef InternalExtractorEdge value_type; + bool operator () (const InternalExtractorEdge & a, const InternalExtractorEdge & b) const { return a.target < b.target; } - value_type max_value() - { - return _Edge::max_value(); + value_type max_value() { + return InternalExtractorEdge::max_value(); } - value_type min_value() - { - return _Edge::min_value(); + value_type min_value() { + return InternalExtractorEdge::min_value(); } }; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index d86fbc457..222475db6 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -332,8 +332,8 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { } inline void PBFParser::parseWay(_ThreadData * threadData) { - _Way w; - std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); + ExtractionWay w; + std::vector waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { w.Clear(); const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); @@ -356,7 +356,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { unsigned endi_ways = waysToParse.size(); #pragma omp parallel for schedule ( guided ) for(unsigned i = 0; i < endi_ways; ++i) { - _Way & w = waysToParse[i]; + ExtractionWay & w = waysToParse[i]; /** Pass the unpacked way to the LUA call back **/ try { luabind::call_function( @@ -376,7 +376,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { // } } - BOOST_FOREACH(_Way & w, waysToParse) { + BOOST_FOREACH(ExtractionWay & w, waysToParse) { if(!externalMemory->wayFunction(w)) { std::cerr << "[PBFParser] way not parsed" << std::endl; } diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index ed469272d..d3da02706 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -41,7 +41,7 @@ #include "ExtractorStructs.h" #include "ScriptingEnvironment.h" -class PBFParser : public BaseParser { +class PBFParser : public BaseParser { enum EntityType { TypeNode = 1, diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index 330eac6af..6bab21c5f 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -65,18 +65,19 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { ]; luabind::module(myLuaState) [ - luabind::class_<_Way>("Way") + luabind::class_("Way") .def(luabind::constructor<>()) - .def_readwrite("name", &_Way::name) - .def_readwrite("speed", &_Way::speed) - .def_readwrite("duration", &_Way::duration) - .def_readwrite("type", &_Way::type) - .def_readwrite("access", &_Way::access) - .def_readwrite("roundabout", &_Way::roundabout) - .def_readwrite("is_access_restricted", &_Way::isAccessRestricted) - .def_readwrite("ignore_in_grid", &_Way::ignoreInGrid) - .def_readwrite("tags", &_Way::keyVals) - .def_readwrite("direction", &_Way::direction) + .def_readwrite("name", &ExtractionWay::name) + .def_readwrite("speed", &ExtractionWay::speed) + .def_readwrite("backward_speed", &ExtractionWay::backward_speed) + .def_readwrite("duration", &ExtractionWay::duration) + .def_readwrite("type", &ExtractionWay::type) + .def_readwrite("access", &ExtractionWay::access) + .def_readwrite("roundabout", &ExtractionWay::roundabout) + .def_readwrite("is_access_restricted", &ExtractionWay::isAccessRestricted) + .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid) + .def_readwrite("tags", &ExtractionWay::keyVals) + .def_readwrite("direction", &ExtractionWay::direction) .enum_("constants") [ luabind::value("notSure", 0), diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 6b2c8a97d..64ef2e25b 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -100,7 +100,7 @@ bool XMLParser::Parse() { } if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { - _Way way = _ReadXMLWay( ); + ExtractionWay way = _ReadXMLWay( ); /** Pass the unpacked way to the LUA call back **/ try { @@ -221,8 +221,8 @@ _RawRestrictionContainer XMLParser::_ReadXMLRestriction() { return restriction; } -_Way XMLParser::_ReadXMLWay() { - _Way way; +ExtractionWay XMLParser::_ReadXMLWay() { + ExtractionWay way; if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { const int depth = xmlTextReaderDepth( inputReader ); while ( xmlTextReaderRead( inputReader ) == 1 ) { diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index d87c50145..3bc54825d 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -28,7 +28,7 @@ #include "ExtractorCallbacks.h" #include "ScriptingEnvironment.h" -class XMLParser : public BaseParser { +class XMLParser : public BaseParser { public: XMLParser(const char * filename); virtual ~XMLParser(); @@ -39,7 +39,7 @@ public: private: _RawRestrictionContainer _ReadXMLRestriction(); - _Way _ReadXMLWay(); + ExtractionWay _ReadXMLWay(); ImportNode _ReadXMLNode( ); /* Input Reader */ xmlTextReaderPtr inputReader; diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index b22086c39..40bc98a9c 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -101,7 +101,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL short type; NodeID nameID; int length; - bool isRoundabout, ignoreInGrid, isAccessRestricted; + bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow; for (EdgeID i=0; i& edgeL in.read((char*)&isRoundabout, sizeof(bool)); in.read((char*)&ignoreInGrid, sizeof(bool)); in.read((char*)&isAccessRestricted, sizeof(bool)); + in.read((char*)&isContraFlow, sizeof(bool)); GUARANTEE(length > 0, "loaded null length edge" ); GUARANTEE(weight > 0, "loaded null weight"); @@ -150,7 +151,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL std::swap(forward, backward); } - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted ); + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow ); edgeList.push_back(inputEdge); } std::sort(edgeList.begin(), edgeList.end()); diff --git a/extractor.cpp b/extractor.cpp index d212a837e..1aa72f83b 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -58,7 +58,6 @@ int main (int argc, char *argv[]) { } omp_set_num_threads(numberOfThreads); - INFO("extracting data from input file " << argv[1]); bool isPBF(false); std::string outputFileName(argv[1]); @@ -93,10 +92,9 @@ int main (int argc, char *argv[]) { StringMap stringMap; ExtractionContainers externalMemory; - stringMap[""] = 0; extractCallBacks = new ExtractorCallbacks(&externalMemory, &stringMap); - BaseParser * parser; + BaseParser * parser; if(isPBF) { parser = new PBFParser(argv[1]); } else { diff --git a/features/bicycle/access.feature b/features/bicycle/access.feature index 149a2743c..cb1fc0d0b 100644 --- a/features/bicycle/access.feature +++ b/features/bicycle/access.feature @@ -1,5 +1,5 @@ @routing @bicycle @access -Feature: Bike - Restricted access +Feature: Bike - Access tags on ways Reference: http://wiki.openstreetmap.org/wiki/Key:access Background: @@ -7,37 +7,95 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access Scenario: Bike - Access tag hierachy on ways Then routability should be - | access | vehicle | bicycle | bothw | - | | | | x | - | yes | | | x | - | no | | | | - | | yes | | x | - | | no | | | - | no | yes | | x | - | yes | no | | | - | | | yes | x | - | | | no | | - | no | | yes | x | - | yes | | no | | - | | no | yes | x | - | | yes | no | | + | highway | access | vehicle | bicycle | bothw | + | | | | | x | + | | yes | | | x | + | | no | | | | + | | | yes | | x | + | | | no | | | + | | no | yes | | x | + | | yes | no | | | + | | | | yes | x | + | | | | no | | + | | no | | yes | x | + | | yes | | no | | + | | | no | yes | x | + | | | yes | no | | + | runway | | | | | + | runway | yes | | | x | + | runway | no | | | | + | runway | | yes | | x | + | runway | | no | | | + | runway | no | yes | | x | + | runway | yes | no | | | + | runway | | | yes | x | + | runway | | | no | | + | runway | no | | yes | x | + | runway | yes | | no | | + | runway | | no | yes | x | + | runway | | yes | no | | - Scenario: Bike - Access tag hierachy on nodes - Then routability should be - | node/access | node/vehicle | node/bicycle | bothw | - | | | | x | - | yes | | | x | - | no | | | | - | | yes | | x | - | | no | | | - | no | yes | | x | - | yes | no | | | - | | | yes | x | - | | | no | | - | no | | yes | x | - | yes | | no | | - | | no | yes | x | - | | yes | no | | + @todo + Scenario: Bike - Access tag in forward direction + Then routability should be + | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw | + | | | | | x | | + | | yes | | | x | | + | | no | | | | | + | | | yes | | x | | + | | | no | | | | + | | no | yes | | x | | + | | yes | no | | | | + | | | | yes | x | | + | | | | no | | | + | | no | | yes | x | | + | | yes | | no | | | + | | | no | yes | x | | + | | | yes | no | | | + | runway | | | | x | | + | runway | yes | | | x | | + | runway | no | | | | | + | runway | | yes | | x | | + | runway | | no | | | | + | runway | no | yes | | x | | + | runway | yes | no | | | | + | runway | | | yes | x | | + | runway | | | no | | | + | runway | no | | yes | x | | + | runway | yes | | no | | | + | runway | | no | yes | x | | + | runway | | yes | no | | | + + @todo + Scenario: Bike - Access tag in backward direction + Then routability should be + | highway | access:forward | vehicle:forward | bicycle:forward | forw | backw | + | | | | | | x | + | | yes | | | | x | + | | no | | | | | + | | | yes | | | x | + | | | no | | | | + | | no | yes | | | x | + | | yes | no | | | | + | | | | yes | | x | + | | | | no | | | + | | no | | yes | | x | + | | yes | | no | | | + | | | no | yes | | x | + | | | yes | no | | | + | runway | | | | | x | + | runway | yes | | | | x | + | runway | no | | | | | + | runway | | yes | | | x | + | runway | | no | | | | + | runway | no | yes | | | x | + | runway | yes | no | | | | + | runway | | | yes | | x | + | runway | | | no | | | + | runway | no | | yes | | x | + | runway | yes | | no | | | + | runway | | no | yes | | x | + | runway | | yes | no | | | Scenario: Bike - Overwriting implied acccess on ways Then routability should be @@ -51,18 +109,6 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access | runway | | yes | | x | | runway | | | yes | x | - Scenario: Bike - Overwriting implied acccess on nodes - Then routability should be - | highway | node/access | node/vehicle | node/bicycle | bothw | - | cycleway | | | | x | - | runway | | | | | - | cycleway | no | | | | - | cycleway | | no | | | - | cycleway | | | no | | - | runway | yes | | | | - | runway | | yes | | | - | runway | | | yes | | - Scenario: Bike - Access tags on ways Then routability should be | access | vehicle | bicycle | bothw | @@ -92,35 +138,6 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access | | | agricultural | | | | | forestery | | - Scenario: Bike - Access tags on nodes - Then routability should be - | node/access | node/vehicle | node/bicycle | bothw | - | | | | x | - | yes | | | x | - | permissive | | | x | - | designated | | | x | - | some_tag | | | x | - | no | | | | - | private | | | | - | agricultural | | | | - | forestery | | | | - | | yes | | x | - | | permissive | | x | - | | designated | | x | - | | some_tag | | x | - | | no | | | - | | private | | | - | | agricultural | | | - | | forestery | | | - | | | yes | x | - | | | permissive | x | - | | | designated | x | - | | | some_tag | x | - | | | no | | - | | | private | | - | | | agricultural | | - | | | forestery | | - Scenario: Bike - Access tags on both node and way Then routability should be | access | node/access | bothw | @@ -147,10 +164,10 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:access Scenario: Bike - Ignore access tags for other modes Then routability should be - | highway | foot | motor_vehicle | moped | bothw | - | runway | yes | | | | + | highway | boat | motor_vehicle | moped | bothw | + | river | yes | | | | | cycleway | no | | | x | | runway | | yes | | | | cycleway | | no | | x | | runway | | | yes | | - | cycleway | | | no | x | \ No newline at end of file + | cycleway | | | no | x | diff --git a/features/bicycle/access_node.feature b/features/bicycle/access_node.feature new file mode 100644 index 000000000..eba808d52 --- /dev/null +++ b/features/bicycle/access_node.feature @@ -0,0 +1,64 @@ +@routing @bicycle @access +Feature: Bike - Access tags on nodes +Reference: http://wiki.openstreetmap.org/wiki/Key:access + + Background: + Given the profile "bicycle" + + Scenario: Bike - Access tag hierachy on nodes + Then routability should be + | node/access | node/vehicle | node/bicycle | bothw | + | | | | x | + | yes | | | x | + | no | | | | + | | yes | | x | + | | no | | | + | no | yes | | x | + | yes | no | | | + | | | yes | x | + | | | no | | + | no | | yes | x | + | yes | | no | | + | | no | yes | x | + | | yes | no | | + + Scenario: Bike - Overwriting implied acccess on nodes + Then routability should be + | highway | node/access | node/vehicle | node/bicycle | bothw | + | cycleway | | | | x | + | runway | | | | | + | cycleway | no | | | | + | cycleway | | no | | | + | cycleway | | | no | | + | runway | yes | | | | + | runway | | yes | | | + | runway | | | yes | | + + Scenario: Bike - Access tags on nodes + Then routability should be + | node/access | node/vehicle | node/bicycle | bothw | + | | | | x | + | yes | | | x | + | permissive | | | x | + | designated | | | x | + | some_tag | | | x | + | no | | | | + | private | | | | + | agricultural | | | | + | forestery | | | | + | | yes | | x | + | | permissive | | x | + | | designated | | x | + | | some_tag | | x | + | | no | | | + | | private | | | + | | agricultural | | | + | | forestery | | | + | | | yes | x | + | | | permissive | x | + | | | designated | x | + | | | some_tag | x | + | | | no | | + | | | private | | + | | | agricultural | | + | | | forestery | | \ No newline at end of file diff --git a/features/bicycle/cycleway.feature b/features/bicycle/cycleway.feature index bf42563ff..f26029453 100644 --- a/features/bicycle/cycleway.feature +++ b/features/bicycle/cycleway.feature @@ -29,16 +29,16 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway Then routability should be | highway | cycleway | cycleway:left | cycleway:right | forw | backw | | primary | | | | x | x | - | pirmary | track | | | x | x | - | pirmary | opposite | | | x | x | - | pirmary | | track | | x | x | - | pirmary | | opposite | | x | x | - | pirmary | | | track | x | x | - | pirmary | | | opposite | x | x | - | pirmary | | track | track | x | x | - | pirmary | | opposite | opposite | x | x | - | pirmary | | track | opposite | x | x | - | pirmary | | opposite | track | x | x | + | primary | track | | | x | x | + | primary | opposite | | | x | x | + | primary | | track | | x | x | + | primary | | opposite | | x | x | + | primary | | | track | x | x | + | primary | | | opposite | x | x | + | primary | | track | track | x | x | + | primary | | opposite | opposite | x | x | + | primary | | track | opposite | x | x | + | primary | | opposite | track | x | x | Scenario: Bike - Left/right side cycleways on implied oneways Then routability should be diff --git a/features/bicycle/maxspeed.feature b/features/bicycle/maxspeed.feature index 9df5029de..b02fe4e33 100644 --- a/features/bicycle/maxspeed.feature +++ b/features/bicycle/maxspeed.feature @@ -36,3 +36,35 @@ Feature: Bike - Max speed restrictions | residential | | 40s ~10% | | residential | none | 40s ~10% | | residential | signals | 40s ~10% | + + Scenario: Bike - Do not use maxspeed when higher that way type speed + Given the node map + | a | b | c | + + And the ways + | nodes | highway | maxspeed | + | ab | residential | | + | bc | residential | 80 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 20s ~5% | + | b | c | bc | 20s ~5% | + + Scenario: Bike - Forward/backward maxspeed + Given the shortcuts + | key | value | + | bike | 43s ~10% | + | run | 73s ~10% | + | walk | 145s ~10% | + | snail | 720s ~10% | + + Then routability should be + | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | | | | bike | bike | + | 10 | | | run | run | + | | 10 | | run | bike | + | | | 10 | bike | run | + | 1 | 10 | | run | snail | + | 1 | | 10 | snail | run | + | 1 | 5 | 10 | walk | run | diff --git a/features/bicycle/oneway.feature b/features/bicycle/oneway.feature index 4e6cb4f2d..6a9d3bf02 100644 --- a/features/bicycle/oneway.feature +++ b/features/bicycle/oneway.feature @@ -1,19 +1,20 @@ @routing @bicycle @oneway Feature: Bike - Oneway streets Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tags_for_routing +Usually we can push bikes against oneways, but we use foot=no to prevent this in these tests Background: Given the profile "bicycle" Scenario: Bike - Simple oneway Then routability should be - | highway | oneway | forw | backw | - | primary | yes | x | | + | highway | foot | oneway | forw | backw | + | primary | no | yes | x | | Scenario: Simple reverse oneway Then routability should be - | highway | oneway | forw | backw | - | primary | -1 | | x | + | highway | foot | oneway | forw | backw | + | primary | no | -1 | | x | Scenario: Bike - Around the Block Given the node map @@ -21,11 +22,11 @@ Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tag | d | c | And the ways - | nodes | oneway | - | ab | yes | - | bc | | - | cd | | - | da | | + | nodes | oneway | foot | + | ab | yes | no | + | bc | | no | + | cd | | no | + | da | | no | When I route I should get | from | to | route | @@ -34,80 +35,80 @@ Handle oneways streets, as defined at http://wiki.openstreetmap.org/wiki/OSM_tag Scenario: Bike - Handle various oneway tag values Then routability should be - | oneway | forw | backw | - | | x | x | - | nonsense | x | x | - | no | x | x | - | false | x | x | - | 0 | x | x | - | yes | x | | - | true | x | | - | 1 | x | | - | -1 | | x | + | foot | oneway | forw | backw | + | no | | x | x | + | no | nonsense | x | x | + | no | no | x | x | + | no | false | x | x | + | no | 0 | x | x | + | no | yes | x | | + | no | true | x | | + | no | 1 | x | | + | no | -1 | | x | Scenario: Bike - Implied oneways Then routability should be - | highway | bicycle | junction | forw | backw | - | | | | x | x | - | | | roundabout | x | | - | motorway | yes | | x | | - | motorway_link | yes | | x | | - | motorway | yes | roundabout | x | | - | motorway_link | yes | roundabout | x | | + | highway | foot | bicycle | junction | forw | backw | + | | no | | | x | x | + | | no | | roundabout | x | | + | motorway | no | yes | | x | | + | motorway_link | no | yes | | x | | + | motorway | no | yes | roundabout | x | | + | motorway_link | no | yes | roundabout | x | | Scenario: Bike - Overriding implied oneways Then routability should be - | highway | junction | oneway | forw | backw | - | primary | roundabout | no | x | x | - | primary | roundabout | yes | x | | - | motorway_link | | -1 | | | - | trunk_link | | -1 | | | - | primary | roundabout | -1 | | x | + | highway | foot | junction | oneway | forw | backw | + | primary | no | roundabout | no | x | x | + | primary | no | roundabout | yes | x | | + | motorway_link | no | | -1 | | | + | trunk_link | no | | -1 | | | + | primary | no | roundabout | -1 | | x | Scenario: Bike - Oneway:bicycle should override normal oneways tags Then routability should be - | oneway:bicycle | oneway | junction | forw | backw | - | yes | | | x | | - | yes | yes | | x | | - | yes | no | | x | | - | yes | -1 | | x | | - | yes | | roundabout | x | | - | no | | | x | x | - | no | yes | | x | x | - | no | no | | x | x | - | no | -1 | | x | x | - | no | | roundabout | x | x | - | -1 | | | | x | - | -1 | yes | | | x | - | -1 | no | | | x | - | -1 | -1 | | | x | - | -1 | | roundabout | | x | + | foot | oneway:bicycle | oneway | junction | forw | backw | + | no | yes | | | x | | + | no | yes | yes | | x | | + | no | yes | no | | x | | + | no | yes | -1 | | x | | + | no | yes | | roundabout | x | | + | no | no | | | x | x | + | no | no | yes | | x | x | + | no | no | no | | x | x | + | no | no | -1 | | x | x | + | no | no | | roundabout | x | x | + | no | -1 | | | | x | + | no | -1 | yes | | | x | + | no | -1 | no | | | x | + | no | -1 | -1 | | | x | + | no | -1 | | roundabout | | x | Scenario: Bike - Contra flow Then routability should be - | oneway | cycleway | forw | backw | - | yes | opposite | x | x | - | yes | opposite_track | x | x | - | yes | opposite_lane | x | x | - | -1 | opposite | x | x | - | -1 | opposite_track | x | x | - | -1 | opposite_lane | x | x | - | no | opposite | x | x | - | no | opposite_track | x | x | - | no | opposite_lane | x | x | + | foot | oneway | cycleway | forw | backw | + | no | yes | opposite | x | x | + | no | yes | opposite_track | x | x | + | no | yes | opposite_lane | x | x | + | no | -1 | opposite | x | x | + | no | -1 | opposite_track | x | x | + | no | -1 | opposite_lane | x | x | + | no | no | opposite | x | x | + | no | no | opposite_track | x | x | + | no | no | opposite_lane | x | x | Scenario: Bike - Should not be affected by car tags Then routability should be - | junction | oneway | oneway:car | forw | backw | - | | yes | yes | x | | - | | yes | no | x | | - | | yes | -1 | x | | - | | no | yes | x | x | - | | no | no | x | x | - | | no | -1 | x | x | - | | -1 | yes | | x | - | | -1 | no | | x | - | | -1 | -1 | | x | - | roundabout | | yes | x | | - | roundabout | | no | x | | - | roundabout | | -1 | x | | + | foot | junction | oneway | oneway:car | forw | backw | + | no | | yes | yes | x | | + | no | | yes | no | x | | + | no | | yes | -1 | x | | + | no | | no | yes | x | x | + | no | | no | no | x | x | + | no | | no | -1 | x | x | + | no | | -1 | yes | | x | + | no | | -1 | no | | x | + | no | | -1 | -1 | | x | + | no | roundabout | | yes | x | | + | no | roundabout | | no | x | | + | no | roundabout | | -1 | x | | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature new file mode 100644 index 000000000..37dff3d1f --- /dev/null +++ b/features/bicycle/pushing.feature @@ -0,0 +1,72 @@ +@routing @bicycle @pushing +Feature: Bike - Accessability of different way types + + Background: + Given the profile "bicycle" + Given the shortcuts + | key | value | + | bike | 40s ~20% | + | foot | 180s ~20% | + + Scenario: Bike - Pushing bikes on pedestrian-only ways + Then routability should be + | highway | oneway | forw | backw | + | (nil) | | | | + | cycleway | | bike | bike | + | primary | | bike | bike | + | pedestrian | | foot | foot | + | footway | | foot | foot | + | primary | yes | bike | foot | + + Scenario: Bike - Pushing bikes against normal oneways + Then routability should be + | highway | oneway | forw | backw | + | (nil) | | | | + | primary | yes | bike | foot | + | pedestrian | yes | foot | foot | + + Scenario: Bike - Pushing bikes against reverse oneways + Then routability should be + | highway | oneway | forw | backw | + | (nil) | | | | + | primary | -1 | foot | bike | + | pedestrian | -1 | foot | foot | + + @square + Scenario: Bike - Push bikes on pedestrian areas + Given the node map + | x | | + | a | b | + | d | c | + + And the ways + | nodes | area | highway | + | xa | | primary | + | abcda | yes | pedestrian | + + When I route I should get + | from | to | route | + | a | b | abcda | + | a | d | abcda | + | b | c | abcda | + | c | b | abcda | + | c | d | abcda | + | d | c | abcda | + | d | a | abcda | + | a | d | abcda | + + Scenario: Bike - Pushing bikes on ways with foot=yes + Then routability should be + | highway | foot | bothw | + | motorway | | | + | motorway | yes | foot | + | runway | | | + | runway | yes | foot | + + @todo + Scenario: Bike - Pushing bikes on ways with foot=yes in one direction + Then routability should be + | highway | foot:forward | foot:backward | forw | backw | + | motorway | | | | | + | motorway | yes | | foot | | + | motorway | | yes | | foot | diff --git a/features/bicycle/restrictions.feature b/features/bicycle/restrictions.feature index 6c5daf70b..27c5c353e 100644 --- a/features/bicycle/restrictions.feature +++ b/features/bicycle/restrictions.feature @@ -3,7 +3,7 @@ Feature: Bike - Turn restrictions Handle turn restrictions as defined by http://wiki.openstreetmap.org/wiki/Relation:restriction Note that if u-turns are allowed, turn restrictions can lead to suprising, but correct, routes. - Background: Use car routing + Background: Given the profile "bicycle" @no_turning @@ -14,11 +14,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -38,11 +38,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -62,11 +62,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -86,11 +86,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -110,11 +110,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -134,11 +134,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -158,11 +158,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -182,11 +182,11 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | nj | -1 | - | wj | -1 | - | ej | -1 | + | nodes | oneway | foot | + | sj | yes | no | + | nj | -1 | no | + | wj | -1 | no | + | ej | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | @@ -206,13 +206,13 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | no | - | xj | -1 | - | aj | -1 | - | bj | no | - | cj | -1 | - | dj | -1 | + | nodes | oneway | foot | + | sj | no | no | + | xj | -1 | no | + | aj | -1 | no | + | bj | no | no | + | cj | -1 | no | + | dj | -1 | no | And the relations | type | way:from | way:to | node:via | restriction | except | @@ -236,10 +236,10 @@ Feature: Bike - Turn restrictions | | s | | And the ways - | nodes | oneway | - | sj | yes | - | aj | no | - | bj | no | + | nodes | oneway | foot | + | sj | yes | no | + | aj | no | no | + | bj | no | no | And the relations | type | way:from | way:to | node:via | restriction | except | @@ -261,14 +261,14 @@ Feature: Bike - Turn restrictions | | | f | And the ways - | nodes | oneway | - | sj | yes | - | ja | yes | - | jb | yes | - | jc | yes | - | jd | yes | - | je | yes | - | jf | yes | + | nodes | oneway | foot | + | sj | yes | no | + | ja | yes | no | + | jb | yes | no | + | jc | yes | no | + | jd | yes | no | + | je | yes | no | + | jf | yes | no | And the relations | type | way:from | way:to | node:via | restriction | except | diff --git a/features/bicycle/way.feature b/features/bicycle/way.feature index ca157bd25..f5ad5bb87 100644 --- a/features/bicycle/way.feature +++ b/features/bicycle/way.feature @@ -4,32 +4,38 @@ Feature: Bike - Accessability of different way types Background: Given the profile "bicycle" - Scenario: Bike - Basic access + Scenario: Bike - Routability of way types Bikes are allowed on footways etc because you can pull your bike at a lower speed. - Given the profile "bicycle" + Pier is not allowed, since it's tagged using man_made=pier. Then routability should be - | highway | forw | - | (nil) | | - | motorway | | - | motorway_link | | - | trunk | | - | trunk_link | | - | primary | x | - | primary_link | x | - | secondary | x | - | secondary_link | x | - | tertiary | x | - | tertiary_link | x | - | residential | x | - | service | x | - | unclassified | x | - | living_street | x | - | road | x | - | track | x | - | path | x | - | footway | x | - | pedestrian | x | - | steps | x | - | pier | x | - | cycleway | x | - | bridleway | | + | highway | bothw | + | (nil) | | + | motorway | | + | motorway_link | | + | trunk | | + | trunk_link | | + | primary | x | + | primary_link | x | + | secondary | x | + | secondary_link | x | + | tertiary | x | + | tertiary_link | x | + | residential | x | + | service | x | + | unclassified | x | + | living_street | x | + | road | x | + | track | x | + | path | x | + | footway | x | + | pedestrian | x | + | steps | x | + | cycleway | x | + | bridleway | | + | pier | | + + Scenario: Bike - Routability of man_made structures + Then routability should be + | highway | man_made | bothw | + | (nil) | (nil) | | + | (nil) | pier | x | diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index 639c1a1e4..7da5088f4 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -10,9 +10,9 @@ Feature: Car - Max speed restrictions | a | b | c | And the ways - | nodes | highway | maxspeed | - | ab | trunk | | - | bc | trunk | 10 | + | nodes | highway | maxspeed | + | ab | trunk | | + | bc | trunk | 10 | When I route I should get | from | to | route | time | @@ -32,3 +32,23 @@ Feature: Car - Max speed restrictions | from | to | route | time | | a | b | ab | 144s ~10% | | b | c | bc | 63s ~10% | + + Scenario: Car - Forward/backward maxspeed + Given the shortcuts + | key | value | + | car | 12s ~10% | + | run | 73s ~10% | + | walk | 146s ~10% | + | snail | 720s ~10% | + + And a grid size of 100 meters + + Then routability should be + | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | | | | car | car | + | 10 | | | run | run | + | | 10 | | run | car | + | | | 10 | car | run | + | 1 | 10 | | run | snail | + | 1 | | 10 | snail | run | + | 1 | 5 | 10 | walk | run | diff --git a/features/car/permissive.feature b/features/car/permissive.feature new file mode 100644 index 000000000..e69de29bb diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 8227c1a75..7ef5ba756 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -46,6 +46,9 @@ When /^I route I should get$/ do |table| if table.headers.include? 'turns' got['turns'] = turns end + if table.headers.include? '#' # comment column + got['#'] = row['#'] # copy value so it always match + end end ok = true @@ -74,4 +77,4 @@ When /^I route (\d+) times I should get$/ do |n,table| ok = false unless step "I route I should get", table end ok -end \ No newline at end of file +end diff --git a/features/support/data.rb b/features/support/data.rb index 8e2e23f76..227a962fc 100644 --- a/features/support/data.rb +++ b/features/support/data.rb @@ -71,14 +71,15 @@ def build_ways_from_table table way << node5 tags = row.dup - #remove tags that describe expected test result + + # remove tags that describe expected test result tags.reject! do |k,v| k =~ /^forw\b/ || k =~ /^backw\b/ || k =~ /^bothw\b/ end - - #remove empty tags + + ##remove empty tags tags.reject! { |k,v| v=='' } # sort tag keys in the form of 'node/....' diff --git a/features/testbot/maxspeed.feature b/features/testbot/maxspeed.feature new file mode 100644 index 000000000..c6b210e48 --- /dev/null +++ b/features/testbot/maxspeed.feature @@ -0,0 +1,52 @@ +@routing @maxspeed @testbot +Feature: Car - Max speed restrictions + + Background: Use specific speeds + Given the profile "testbot" + + Scenario: Testbot - Respect maxspeeds when lower that way type speed + Given the node map + | a | b | c | d | + + And the ways + | nodes | maxspeed | + | ab | | + | bc | 24 | + | cd | 18 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 15s +-1 | + | c | b | bc | 15s +-1 | + | c | d | cd | 20s +-1 | + | d | c | cd | 20s +-1 | + + Scenario: Testbot - Ignore maxspeed when higher than way speed + Given the node map + | a | b | c | + + And the ways + | nodes | maxspeed | + | ab | | + | bc | 200 | + + When I route I should get + | from | to | route | time | + | a | b | ab | 10s +-1 | + | b | a | ab | 10s +-1 | + | b | c | bc | 10s +-1 | + | c | b | bc | 10s +-1 | + + @opposite + Scenario: Testbot - Forward/backward maxspeed + Then routability should be + | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | | | | 20s +-1 | 20s +-1 | + | 18 | | | 40s +-1 | 40s +-1 | + | | 18 | | 40s +-1 | 20s +-1 | + | | | 18 | 20s +-1 | 40s +-1 | + | 9 | 18 | | 40s +-1 | 80s +-1 | + | 9 | | 18 | 80s +-1 | 40s +-1 | + | 9 | 24 | 18 | 30s +-1 | 40s +-1 | \ No newline at end of file diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index 176974965..c242c97b1 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -1,19 +1,18 @@ -@routing @opposite @todo +@routing @testbot @opposite Feature: Separate settings for forward/backward direction Background: Given the profile "testbot" - @smallest - Scenario: Going against the flow + Scenario: Testbot - Going against the flow Given the node map - | a | b | + | a | b | c | d | And the ways | nodes | highway | - | ab | river | + | abcd | river | When I route I should get - | from | to | route | distance | time | - | a | b | ab | 100m | 10s | - | b | a | ab | 100m | 20s | + | from | to | route | distance | time | + | a | d | abcd | 300 +- 1m | 30s | + | d | a | abcd | 300 +- 1m | 68s | \ No newline at end of file diff --git a/profile.lua b/profile.lua deleted file mode 120000 index bad7e6bb5..000000000 --- a/profile.lua +++ /dev/null @@ -1 +0,0 @@ -profiles/car.lua \ No newline at end of file diff --git a/profile.lua b/profile.lua new file mode 100644 index 000000000..bad7e6bb5 --- /dev/null +++ b/profile.lua @@ -0,0 +1 @@ +profiles/car.lua \ No newline at end of file diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 3c14dc250..7d51e8091 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -12,7 +12,9 @@ restriction_exception_tags = { "bicycle", "vehicle", "access" } default_speed = 16 -main_speeds = { +walking_speed = 4 + +bicycle_speeds = { ["cycleway"] = 18, ["primary"] = 17, ["primary_link"] = 17, @@ -26,17 +28,14 @@ main_speeds = { ["road"] = 16, ["service"] = 16, ["track"] = 13, - ["path"] = 13, - ["footway"] = 12, - ["pedestrian"] = 12, - ["pier"] = 12, - ["steps"] = 2 + ["path"] = 13 + --["footway"] = 12, + --["pedestrian"] = 12, } pedestrian_speeds = { - ["footway"] = 5, - ["pedestrian"] = 5, - ["pier"] = 5, + ["footway"] = walking_speed, + ["pedestrian"] = walking_speed, ["steps"] = 2 } @@ -50,7 +49,7 @@ railway_speeds = { } platform_speeds = { - ["platform"] = 5 + ["platform"] = walking_speed } amenity_speeds = { @@ -58,6 +57,10 @@ amenity_speeds = { ["parking_entrance"] = 10 } +man_made_speeds = { + ["pier"] = walking_speed +} + route_speeds = { ["ferry"] = 5 } @@ -110,17 +113,38 @@ function way_function (way, numberOfNodesInWay) if(numberOfNodesInWay < 2) then return 0; end - - -- First, get the properties of each way that we come across + + -- initial routability check, filters out buildings, boundaries, etc local highway = way.tags:Find("highway") + local route = way.tags:Find("route") + local man_made = way.tags:Find("man_made") + local railway = way.tags:Find("railway") + local amenity = way.tags:Find("amenity") + local public_transport = way.tags:Find("public_transport") + if (not highway or highway == '') and + (not route or route == '') and + (not railway or railway=='') and + (not amenity or amenity=='') and + (not man_made or man_made=='') and + (not public_transport or public_transport=='') + then + return 0 + end + + -- access + local access = Access.find_access_tag(way, access_tags_hierachy) + if access_tag_blacklist[access] then + return 0 + end + + + -- other tags local name = way.tags:Find("name") local ref = way.tags:Find("ref") local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local railway = way.tags:Find("railway") - local public_transport = way.tags:Find("public_transport") local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) - local man_made = way.tags:Find("man_made") + local maxspeed_forward = parseMaxspeed(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = parseMaxspeed(way.tags:Find( "maxspeed:backward")) local barrier = way.tags:Find("barrier") local oneway = way.tags:Find("oneway") local onewayClass = way.tags:Find("oneway:bicycle") @@ -130,23 +154,7 @@ function way_function (way, numberOfNodesInWay) local duration = way.tags:Find("duration") local service = way.tags:Find("service") local area = way.tags:Find("area") - local amenity = way.tags:Find("amenity") - local access = Access.find_access_tag(way, access_tags_hierachy) - - -- initial routability check, filters out buildings, boundaries, etc - if (not highway or highway == '') and - (not route or route == '') and - (not railway or railway=='') and - (not amenity or amenity=='') and - (not public_transport or public_transport=='') - then - return 0 - end - - -- access - if access_tag_blacklist[access] then - return 0 - end + local foot = way.tags:Find("foot") -- name if "" ~= ref then @@ -157,8 +165,9 @@ function way_function (way, numberOfNodesInWay) way.name = highway -- if no name exists, use way type end + -- speed if route_speeds[route] then - -- ferries + -- ferries (doesn't cover routes tagged using relations) way.direction = Way.bidirectional way.ignore_in_grid = true if durationIsValid(duration) then @@ -178,34 +187,32 @@ function way_function (way, numberOfNodesInWay) way.speed = railway_speeds[railway] way.direction = Way.bidirectional end - elseif pedestrian_speeds[highway] and main_speeds[highway] then - -- pedestrian areas - if access_tag_whitelist[access] then - way.speed = main_speeds[highway] -- biking - else - way.speed = pedestrian_speeds[highway] -- pushing bikes - end elseif amenity and amenity_speeds[amenity] then -- parking areas way.speed = amenity_speeds[amenity] - else + elseif bicycle_speeds[highway] then -- regular ways - if main_speeds[highway] then - way.speed = main_speeds[highway] - elseif main_speeds[man_made] then - way.speed = main_speeds[man_made] - elseif access_tag_whitelist[access] then - way.speed = default_speed - end - end - - -- maxspeed - if take_minimum_of_speeds then - if maxspeed and maxspeed>0 then - way.speed = math.min(way.speed, maxspeed) - end - end - + way.speed = bicycle_speeds[highway] + elseif access and access_tag_whitelist[access] then + -- unknown way, but valid access tag + way.speed = default_speed + else + -- biking not allowed, maybe we can push our bike? + -- essentially requires pedestrian profiling, for example foot=no mean we can't push a bike + -- TODO: if we can push, the way should be marked as pedestrion mode, but there's no way to do it yet from lua.. + if foot ~= 'no' then + if pedestrian_speeds[highway] then + -- pedestrian-only ways and areas + way.speed = pedestrian_speeds[highway] + elseif man_made and man_made_speeds[man_made] then + -- man made structures + way.speed = man_made_speeds[man_made] + elseif foot == 'yes' then + way.speed = walking_speed + end + end + end + -- direction way.direction = Way.bidirectional local impliedOneway = false @@ -248,15 +255,53 @@ function way_function (way, numberOfNodesInWay) way.direction = Way.oneway end + -- pushing bikes + if bicycle_speeds[highway] or pedestrian_speeds[highway] then + if foot ~= 'no' then + if way.direction == Way.oneway then + way.backward_speed = walking_speed + elseif way.direction == Way.opposite then + way.backward_speed = walking_speed + way.speed = way.speed + end + end + if way.backward_speed == way.speed then + -- TODO: no way yet to mark a way as pedestrian mode if forward/backward speeds are equal + way.direction = Way.bidirectional + end + end + + -- cycleways if cycleway and cycleway_tags[cycleway] then - way.speed = main_speeds["cycleway"] + way.speed = bicycle_speeds["cycleway"] elseif cycleway_left and cycleway_tags[cycleway_left] then - way.speed = main_speeds["cycleway"] + way.speed = bicycle_speeds["cycleway"] elseif cycleway_right and cycleway_tags[cycleway_right] then - way.speed = main_speeds["cycleway"] + way.speed = bicycle_speeds["cycleway"] end + -- maxspeed + -- TODO: maxspeed of backward direction + if take_minimum_of_speeds then + if maxspeed and maxspeed>0 then + way.speed = math.min(way.speed, maxspeed) + end + end + + -- Override speed settings if explicit forward/backward maxspeeds are given + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + if Way.bidirectional == way.direction then + way.backward_speed = way.speed + end + way.speed = maxspeed_forward + end + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + way.backward_speed = maxspeed_backward + end + + + way.type = 1 return 1 end diff --git a/profiles/car.lua b/profiles/car.lua index f123dfdfc..6dfaf5ce1 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -12,24 +12,24 @@ ignore_in_grid = { ["ferry"] = true } restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } speed_profile = { - ["motorway"] = 90, - ["motorway_link"] = 75, - ["trunk"] = 85, - ["trunk_link"] = 70, - ["primary"] = 65, - ["primary_link"] = 60, - ["secondary"] = 55, - ["secondary_link"] = 50, - ["tertiary"] = 40, - ["tertiary_link"] = 30, - ["unclassified"] = 25, - ["residential"] = 25, - ["living_street"] = 10, - ["service"] = 15, + ["motorway"] = 90, + ["motorway_link"] = 75, + ["trunk"] = 85, + ["trunk_link"] = 70, + ["primary"] = 65, + ["primary_link"] = 60, + ["secondary"] = 55, + ["secondary_link"] = 50, + ["tertiary"] = 40, + ["tertiary_link"] = 30, + ["unclassified"] = 25, + ["residential"] = 25, + ["living_street"] = 10, + ["service"] = 15, -- ["track"] = 5, - ["ferry"] = 5, - ["shuttle_train"] = 10, - ["default"] = 50 + ["ferry"] = 5, + ["shuttle_train"] = 10, + ["default"] = 50 } take_minimum_of_speeds = false @@ -43,85 +43,101 @@ u_turn_penalty = 20 -- End of globals function get_exceptions(vector) - for i,v in ipairs(restriction_exception_tags) do - vector:Add(v) - end + for i,v in ipairs(restriction_exception_tags) do + vector:Add(v) + end +end + +local function parse_maxspeed(source) + if source == nil then + return 0 + end + local n = tonumber(source:match("%d*")) + if n == nil then + n = 0 + end + if string.match(source, "mph") or string.match(source, "mp/h") then + n = (n*1609)/1000; + end + return math.abs(n) end function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = Access.find_access_tag(node, access_tags_hierachy) - local traffic_signal = node.tags:Find("highway") - - --flag node if it carries a traffic light - - if traffic_signal == "traffic_signals" then - node.traffic_light = true; - end - - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - return - else - node.bollard = true - end + local barrier = node.tags:Find ("barrier") + local access = Access.find_access_tag(node, access_tags_hierachy) + local traffic_signal = node.tags:Find("highway") + + --flag node if it carries a traffic light + + if traffic_signal == "traffic_signals" then + node.traffic_light = true; end - return 1 + + -- parse access and barrier tags + if access and access ~= "" then + if access_tag_blacklist[access] then + node.bollard = true + end + elseif barrier and barrier ~= "" then + if barrier_whitelist[barrier] then + return + else + node.bollard = true + end + end + return 1 end function way_function (way, numberOfNodesInWay) - -- A way must have two nodes or more - if(numberOfNodesInWay < 2) then - return 0; - end - - -- First, get the properties of each way that we come across - local highway = way.tags:Find("highway") - local name = way.tags:Find("name") - local ref = way.tags:Find("ref") - local junction = way.tags:Find("junction") - local route = way.tags:Find("route") - local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) - local barrier = way.tags:Find("barrier") - local oneway = way.tags:Find("oneway") - local cycleway = way.tags:Find("cycleway") - local duration = way.tags:Find("duration") - local service = way.tags:Find("service") - local area = way.tags:Find("area") - local access = Access.find_access_tag(way, access_tags_hierachy) - - -- Second, parse the way according to these properties - - if ignore_areas and ("yes" == area) then - return 0 - end - - -- Check if we are allowed to access the way - if access_tag_blacklist[access] then - return 0 - end - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name --- else --- way.name = highway -- if no name exists, use way type + -- A way must have two nodes or more + if(numberOfNodesInWay < 2) then + return 0; end - if "roundabout" == junction then - way.roundabout = true; - end + -- First, get the properties of each way that we come across + local highway = way.tags:Find("highway") + local name = way.tags:Find("name") + local ref = way.tags:Find("ref") + local junction = way.tags:Find("junction") + local route = way.tags:Find("route") + local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) + local barrier = way.tags:Find("barrier") + local oneway = way.tags:Find("oneway") + local cycleway = way.tags:Find("cycleway") + local duration = way.tags:Find("duration") + local service = way.tags:Find("service") + local area = way.tags:Find("area") + local access = Access.find_access_tag(way, access_tags_hierachy) - -- Handling ferries and piers + -- Second, parse the way according to these properties + + if ignore_areas and ("yes" == area) then + return 0 + end + + -- Check if we are allowed to access the way + if access_tag_blacklist[access] then + return 0 + end + + -- Set the name that will be used for instructions + if "" ~= ref then + way.name = ref + elseif "" ~= name then + way.name = name +-- else +-- way.name = highway -- if no name exists, use way type + end + + if "roundabout" == junction then + way.roundabout = true; + end + + -- Handling ferries and piers if (speed_profile[route] ~= nil and speed_profile[route] > 0) then if durationIsValid(duration) then way.duration = math.max( parseDuration(duration), 1 ); @@ -134,9 +150,9 @@ function way_function (way, numberOfNodesInWay) way.speed = speed_profile[highway] end end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then + + -- Set the avg speed on the way if it is accessible by road class + if (speed_profile[highway] ~= nil and way.speed == -1 ) then if maxspeed > speed_profile[highway] then way.speed = maxspeed else @@ -146,55 +162,64 @@ function way_function (way, numberOfNodesInWay) way.speed = math.min(speed_profile[highway], maxspeed) end end - - -- Set the avg speed on ways that are marked accessible - if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then - if 0 == maxspeed then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) - end - - if durationIsValid(duration) then - way.duration = math.max( parseDuration(duration), 1 ); - end - -- Set access restriction flag if access is allowed under certain restrictions only - if access ~= "" and access_tag_restricted[access] then - way.is_access_restricted = true - end + -- Set the avg speed on ways that are marked accessible + if "" ~= highway and access_tag_whitelist[access] and way.speed == -1 then + if 0 == maxspeed then + maxspeed = math.huge + end + way.speed = math.min(speed_profile["default"], maxspeed) + end - -- Set access restriction flag if service is allowed under certain restrictions only - if service ~= "" and service_tag_restricted[service] then - way.is_access_restricted = true - end + -- Set access restriction flag if access is allowed under certain restrictions only + if access ~= "" and access_tag_restricted[access] then + way.is_access_restricted = true + end + + -- Set access restriction flag if service is allowed under certain restrictions only + if service ~= "" and service_tag_restricted[service] then + way.is_access_restricted = true + end + + -- Set direction according to tags on way + if obey_oneway then + if oneway == "no" or oneway == "0" or oneway == "false" then + way.direction = Way.bidirectional + elseif oneway == "-1" then + way.direction = Way.opposite + elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then + way.direction = Way.oneway + else + way.direction = Way.bidirectional + end + else + way.direction = Way.bidirectional + end + + -- Override speed settings if explicit forward/backward maxspeeds are given + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + if Way.bidirectional == way.direction then + way.backward_speed = way.speed + end + way.speed = maxspeed_forward + end + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + way.backward_speed = maxspeed_backward + end + + -- Override general direction settings of there is a specific one for our mode of travel - -- Set direction according to tags on way - if obey_oneway then - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" or junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional - end - else - way.direction = Way.bidirectional - end - - -- Override general direction settings of there is a specific one for our mode of travel - if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then - way.ignore_in_grid = true - end - way.type = 1 -return 1 + if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then + way.ignore_in_grid = true + end + way.type = 1 + return 1 end -- These are wrappers to parse vectors of nodes and ways and thus to speed up any tracing JIT + function node_vector_function(vector) -for v in vector.nodes do - node_function(v) -end + for v in vector.nodes do + node_function(v) + end end diff --git a/profiles/testbot.lua b/profiles/testbot.lua index 9c7b103ac..6379cdb70 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -23,6 +23,18 @@ ignore_areas = true -- future feature traffic_signal_penalty = 7 -- seconds u_turn_penalty = 20 +function limit_speed(speed, limits) + -- don't use ipairs(), since it stops at the first nil value + for i=1, #limits do + limit = limits[i] + if limit ~= nil and limit > 0 then + if limit < speed then + return limit -- stop at first speedlimit that's smaller than speed + end + end + end + return speed +end function node_function (node) local traffic_signal = node.tags:Find("highway") @@ -45,13 +57,44 @@ function way_function (way, numberOfNodesInWay) local oneway = way.tags:Find("oneway") local route = way.tags:Find("route") local duration = way.tags:Find("duration") + local maxspeed = tonumber(way.tags:Find ( "maxspeed")) + local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) way.name = name if route ~= nil and durationIsValid(duration) then way.duration = math.max( 1, parseDuration(duration) ) else - way.speed = speed_profile[highway] or speed_profile['default'] + local speed_forw = speed_profile[highway] or speed_profile['default'] + local speed_back = speed_forw + + if highway == "river" then + local temp_speed = speed_forw; + speed_forw = temp_speed*1.5 + speed_back = temp_speed/1.5 + end + + if maxspeed_forward ~= nil and maxspeed_forward > 0 then + speed_forw = maxspeed_forward + else + if maxspeed ~= nil and maxspeed > 0 and speed_forw > maxspeed then + speed_forw = maxspeed + end + end + + if maxspeed_backward ~= nil and maxspeed_backward > 0 then + speed_back = maxspeed_backward + else + if maxspeed ~=nil and maxspeed > 0 and speed_back > maxspeed then + speed_back = maxspeed + end + end + + way.speed = speed_forw + if speed_back ~= way_forw then + way.backward_speed = speed_back + end end if oneway == "no" or oneway == "0" or oneway == "false" then