From b03ccfa014d047800696f1c6bc2ca26ac565efef Mon Sep 17 00:00:00 2001 From: Emil Tin Date: Mon, 18 Mar 2013 19:59:15 +0100 Subject: [PATCH] mode flags --- Algorithms/StronglyConnectedComponents.h | 40 ++- CMakeLists.txt | 2 +- Contractor/ContractionCleanup.h | 2 + Contractor/EdgeBasedGraphFactory.cpp | 31 +-- Contractor/EdgeBasedGraphFactory.h | 5 +- DataStructures/GridEdge.h | 6 +- DataStructures/ImportEdge.h | 17 +- DataStructures/NNGrid.cpp | 113 +++++++++ DataStructures/NNGrid.h | 139 +++------- DataStructures/NodeInformationHelpDesk.h | 14 +- DataStructures/PhantomNodes.h | 5 +- DataStructures/QueryEdge.h | 12 +- DataStructures/SegmentInformation.h | 9 +- DataStructures/TravelMode.h | 26 ++ Descriptors/DescriptionFactory.cpp | 12 +- Descriptors/JSONDescriptor.h | 7 +- Extractor/BaseParser.cpp | 23 ++ Extractor/BaseParser.h | 3 +- Extractor/ExtractionContainers.cpp | 9 +- Extractor/ExtractorCallbacks.cpp | 110 ++++---- Extractor/ExtractorStructs.h | 101 +++++--- Extractor/PBFParser.cpp | 5 +- Extractor/ScriptingEnvironment.cpp | 22 +- Plugins/RawRouteData.h | 3 +- RoutingAlgorithms/AlternativePathRouting.h | 8 +- RoutingAlgorithms/BasicRoutingInterface.h | 7 +- RoutingAlgorithms/ShortestPathRouting.h | 12 +- Server/DataStructures/QueryObjectsStorage.cpp | 4 +- Server/DataStructures/QueryObjectsStorage.h | 2 - Util/GraphLoader.h | 19 +- createHierarchy.cpp | 1 + features/bicycle/cycleway.feature | 2 +- features/bicycle/mode.feature | 132 +++++++--- features/bicycle/pushing.feature | 34 ++- features/step_definitions/routing.rb | 10 +- features/support/route.rb | 4 +- features/testbot/graph.feature | 1 - features/testbot/mode.feature | 164 ++++++++++-- profile.lua | 1 - profiles/bicycle.lua | 164 ++++++------ profiles/car.lua | 42 +-- profiles/foot.lua | 240 ++++++++---------- profiles/lib/maxspeed.lua | 17 ++ profiles/testbot.lua | 71 ++++-- 44 files changed, 1006 insertions(+), 645 deletions(-) create mode 100644 DataStructures/NNGrid.cpp create mode 100644 DataStructures/TravelMode.h create mode 100644 profiles/lib/maxspeed.lua diff --git a/Algorithms/StronglyConnectedComponents.h b/Algorithms/StronglyConnectedComponents.h index a83110034a9..c8c366fb091 100644 --- a/Algorithms/StronglyConnectedComponents.h +++ b/Algorithms/StronglyConnectedComponents.h @@ -52,7 +52,6 @@ class TarjanSCC { unsigned edgeBasedNodeID; unsigned nameID:31; bool shortcut:1; - short type; bool isAccessRestricted:1; bool forward:1; bool backward:1; @@ -165,7 +164,6 @@ class TarjanSCC { edge.data.roundabout = i->isRoundabout(); edge.data.ignoreInGrid = i->ignoreInGrid(); edge.data.nameID = i->name(); - edge.data.type = i->type(); edge.data.isAccessRestricted = i->isAccessRestricted(); edge.data.edgeBasedNodeID = edges.size(); edges.push_back( edge ); @@ -312,27 +310,25 @@ class TarjanSCC { for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) { _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1); - if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) { - assert(e1 != UINT_MAX); - assert(u != UINT_MAX); - assert(v != UINT_MAX); - //edges that end on bollard nodes may actually be in two distinct components - if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) { - - //INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")"); - OGRLineString lineString; - lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.); - lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.); - - OGRFeature *poFeature; - poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() ); - poFeature->SetGeometry( &lineString ); - if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) - { - ERR( "Failed to create feature in shapefile.\n" ); - } - OGRFeature::DestroyFeature( poFeature ); + assert(e1 != UINT_MAX); + assert(u != UINT_MAX); + assert(v != UINT_MAX); + //edges that end on bollard nodes may actually be in two distinct components + if(std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 10) { + + //INFO("(" << inputNodeInfoList[u].lat/100000. << ";" << inputNodeInfoList[u].lon/100000. << ") -> (" << inputNodeInfoList[v].lat/100000. << ";" << inputNodeInfoList[v].lon/100000. << ")"); + OGRLineString lineString; + lineString.addPoint(inputNodeInfoList[u].lon/100000., inputNodeInfoList[u].lat/100000.); + lineString.addPoint(inputNodeInfoList[v].lon/100000., inputNodeInfoList[v].lat/100000.); + + OGRFeature *poFeature; + poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() ); + poFeature->SetGeometry( &lineString ); + if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE ) + { + ERR( "Failed to create feature in shapefile.\n" ); } + OGRFeature::DestroyFeature( poFeature ); } } } diff --git a/CMakeLists.txt b/CMakeLists.txt index 9881da81fe5..d8f557c3a34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ file(GLOB PrepareGlob Contractor/*.cpp) set(PrepareSources createHierarchy.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources}) -file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp) +file(GLOB RoutedGlob Server/DataStructures/*.cpp Descriptors/*.cpp DataStructures/*.cpp) set(RoutedSources routed.cpp ${RoutedGlob}) add_executable(osrm-routed ${RoutedSources}) set_target_properties(osrm-routed PROPERTIES COMPILE_FLAGS -DROUTED) diff --git a/Contractor/ContractionCleanup.h b/Contractor/ContractionCleanup.h index e42dad3a734..3aaba493328 100644 --- a/Contractor/ContractionCleanup.h +++ b/Contractor/ContractionCleanup.h @@ -26,6 +26,7 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #endif #include "Contractor.h" +#include "TravelMode.h" class ContractionCleanup { private: @@ -64,6 +65,7 @@ class ContractionCleanup { bool shortcut:1; bool forward:1; bool backward:1; + TravelMode mode; } data; bool operator<( const Edge& right ) const { if ( source != right.source ) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index fce247d3198..9814a844e98 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -70,10 +70,9 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectorisRoundabout(); edge.data.ignoreInGrid = i->ignoreInGrid(); edge.data.nameID = i->name(); - edge.data.type = i->type(); edge.data.isAccessRestricted = i->isAccessRestricted(); edge.data.edgeBasedNodeID = edges.size(); - edge.data.contraFlow = i->isContraFlow(); + edge.data.mode = i->mode(); edges.push_back( edge ); if( edge.data.backward ) { std::swap( edge.source, edge.target ); @@ -147,6 +146,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( currentNode.id = data.edgeBasedNodeID; currentNode.ignoreInGrid = data.ignoreInGrid; currentNode.weight = data.distance; + currentNode.mode = data.mode; edgeBasedNodes.push_back(currentNode); } @@ -221,13 +221,11 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State for(_NodeBasedDynamicGraph::EdgeIterator e1 = _nodeBasedGraph->BeginEdges(u); e1 < _nodeBasedGraph->EndEdges(u); ++e1) { _NodeBasedDynamicGraph::NodeIterator v = _nodeBasedGraph->GetTarget(e1); - if(_nodeBasedGraph->GetEdgeData(e1).type != SHRT_MAX) { - assert(e1 != UINT_MAX); - assert(u != UINT_MAX); - assert(v != UINT_MAX); - //edges that end on bollard nodes may actually be in two distinct components - InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) ); - } + assert(e1 != UINT_MAX); + assert(u != UINT_MAX); + assert(v != UINT_MAX); + //edges that end on bollard nodes may actually be in two distinct components + InsertEdgeBasedNode(e1, u, v, (std::min(vectorOfComponentSizes[componentsIndex[u]], vectorOfComponentSizes[componentsIndex[v]]) < 1000) ); } } @@ -274,6 +272,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State distance += speedProfile.trafficSignalPenalty; } unsigned penalty = 0; + TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, penalty, myLuaState); if(turnInstruction == TurnInstructions.UTurn) distance += speedProfile.uTurnPenalty; @@ -283,11 +282,10 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State // } distance += penalty; - //distance += heightPenalty; //distance += ComputeTurnPenalty(u, v, w); assert(edgeData1.edgeBasedNodeID != edgeData2.edgeBasedNodeID); - OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction); + OriginalEdgeData oed(v,edgeData2.nameID, turnInstruction, edgeData2.mode); original_edge_data_vector.push_back(oed); ++numberOfOriginalEdges; @@ -351,13 +349,6 @@ 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! @@ -379,8 +370,8 @@ 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 street names and modes stay the same and if we are certain that it is not a roundabout, we skip it. + if( (data1.nameID == data2.nameID) && (data1.mode == data2.mode) && (0 != data1.nameID)) { return TurnInstructions.NoTurn; } if( (data1.nameID == data2.nameID) && (0 == data1.nameID) && (_nodeBasedGraph->GetOutDegree(v) <= 2) ) { diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index e751a716992..a8f3e4db1fe 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -77,6 +77,7 @@ class EdgeBasedGraphFactory : boost::noncopyable { NodeID nameID; unsigned weight:31; bool ignoreInGrid:1; + TravelMode mode; }; struct SpeedProfileProperties{ @@ -91,14 +92,13 @@ class EdgeBasedGraphFactory : boost::noncopyable { int distance; unsigned edgeBasedNodeID; unsigned nameID; - short type; bool isAccessRestricted:1; bool shortcut:1; bool forward:1; bool backward:1; bool roundabout:1; bool ignoreInGrid:1; - bool contraFlow:1; + TravelMode mode; }; struct _EdgeBasedEdgeData { @@ -108,6 +108,7 @@ class EdgeBasedGraphFactory : boost::noncopyable { bool forward; bool backward; TurnInstruction turnInstruction; + TravelMode mode; }; typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; diff --git a/DataStructures/GridEdge.h b/DataStructures/GridEdge.h index 7b2dd7825cd..a7f633374d8 100644 --- a/DataStructures/GridEdge.h +++ b/DataStructures/GridEdge.h @@ -22,16 +22,18 @@ or see http://www.gnu.org/licenses/agpl.txt. #define GRIDEDGE_H_ #include "Coordinate.h" +#include "TravelMode.h" struct _GridEdge { - _GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc) {} - _GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false) {} + _GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc, bool bttc, TravelMode _mode) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc), belongsToTinyComponent(bttc), mode(_mode) {} + _GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX), belongsToTinyComponent(false), mode(0) {} NodeID edgeBasedNode; NodeID nameID; int weight; _Coordinate startCoord; _Coordinate targetCoord; bool belongsToTinyComponent; + TravelMode mode; bool operator< ( const _GridEdge& right) const { return edgeBasedNode < right.edgeBasedNode; diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index 714560ccc8e..772037a0c48 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -23,6 +23,8 @@ or see http://www.gnu.org/licenses/agpl.txt. #include +#include "TravelMode.h" + class NodeBasedEdge { public: @@ -40,22 +42,20 @@ class NodeBasedEdge { return (source() < e.source()); } - 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);}; } + explicit NodeBasedEdge(NodeID s, NodeID t, NodeID n, EdgeWeight w, bool f, bool b, bool ra, bool ig, bool ar, TravelMode mode) : + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _mode(mode) {} NodeID target() const {return _target; } NodeID source() const {return _source; } NodeID name() const { return _name; } EdgeWeight weight() const {return _weight; } - short type() const { assert(_type >= 0); return _type; } bool isBackward() const { return backward; } bool isForward() const { return forward; } - bool isLocatable() const { return _type != 14; } bool isRoundabout() const { return _roundabout; } bool ignoreInGrid() const { return _ignoreInGrid; } bool isAccessRestricted() const { return _accessRestricted; } - bool isContraFlow() const { return _contraFlow; } + TravelMode mode() const { return _mode; } NodeID _source; NodeID _target; @@ -63,16 +63,15 @@ class NodeBasedEdge { EdgeWeight _weight; bool forward; bool backward; - short _type; bool _roundabout; bool _ignoreInGrid; bool _accessRestricted; - bool _contraFlow; + TravelMode _mode; 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. + _source(0), _target(0), _name(0), _weight(0), forward(0), backward(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _mode(0) { assert(false); } //shall not be used. }; @@ -127,7 +126,7 @@ class EdgeBasedEdge { EdgeWeight weight() const {return m_weight; } NodeID id() const { return m_edgeID; } bool isBackward() const { return m_backward; } - bool isForward() const { return m_forward; } + bool isForward() const { return m_forward; } private: NodeID m_source; NodeID m_target; diff --git a/DataStructures/NNGrid.cpp b/DataStructures/NNGrid.cpp new file mode 100644 index 00000000000..2bb64fc0d14 --- /dev/null +++ b/DataStructures/NNGrid.cpp @@ -0,0 +1,113 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, others 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#include "../typedefs.h" +#include "NNGrid.h" +#include "NodeInformationHelpDesk.h" + +bool NNGrid::FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) { + bool ignoreTinyComponents = (zoomLevel <= 14); +// INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no")); +// double time1 = get_timestamp(); + bool foundNode = false; + const _Coordinate startCoord(100000*(lat2y(static_cast(location.lat)/100000.)), location.lon); + /** search for point on edge close to source */ + const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon); + std::vector<_GridEdge> candidates; + const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768); + for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) { + for(int i = -1; i < 2; ++i){ +// unsigned oldSize = candidates.size(); + GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates); +// INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates"); + } + } +// INFO("looked up " << candidates.size()); + _GridEdge smallestEdge; + _Coordinate tmp, edgeStartCoord, edgeEndCoord; + double dist = std::numeric_limits::max(); + double r, tmpDist; + + BOOST_FOREACH(const _GridEdge & candidate, candidates) { + if(candidate.belongsToTinyComponent && ignoreTinyComponents) + continue; + r = 0.; + tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r); +// INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist ); +// INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist); + if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) { +// INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no")); + dist = tmpDist; + resultNode.edgeBasedNode = candidate.edgeBasedNode; + resultNode.nodeBasedEdgeNameID = candidate.nameID; + resultNode.mode1 = candidate.mode; + resultNode.mode2 = 0; + resultNode.weight1 = candidate.weight; + resultNode.weight2 = INT_MAX; + resultNode.location.lat = tmp.lat; + resultNode.location.lon = tmp.lon; + edgeStartCoord = candidate.startCoord; + edgeEndCoord = candidate.targetCoord; + foundNode = true; + smallestEdge = candidate; + //} else if(tmpDist < dist) { + //INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist)); + } else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast(candidate.edgeBasedNode)-static_cast(resultNode.edgeBasedNode) ) && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) { + resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode); + resultNode.weight2 = candidate.weight; + resultNode.mode2 = candidate.mode; + //INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist); + } + } + + // INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint); + // INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)); + // INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint)); + // assert(!resultNode.isBidirected() || (resultNode.weight1 == resultNode.weight2)); + // if(resultNode.weight1 != resultNode.weight2) { + // INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2); + // INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no")); + // } + +// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location); + 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. + if(std::abs(location.lon - resultNode.location.lon) == 1) + resultNode.location.lon = location.lon; + if(std::abs(location.lat - resultNode.location.lat) == 1) + resultNode.location.lat = location.lat; + + resultNode.weight1 *= ratio; + if(INT_MAX != resultNode.weight2) { + resultNode.weight2 *= (1.-ratio); + } + resultNode.ratio = ratio; +// INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord); +// 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/NNGrid.h b/DataStructures/NNGrid.h index 22cb4e2d4df..51ea4e10879 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -51,37 +51,31 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "StaticGraph.h" #include "TimingUtil.h" #include "../Algorithms/Bresenham.h" +#include "QueryEdge.h" -namespace NNGrid{ +class NodeInformationHelpDesk; +class QueryGraph; static boost::thread_specific_ptr localStream; -template + class NNGrid { public: - NNGrid() /*: cellCache(500), fileCache(500)*/ { - ramIndexTable.resize((1024*1024), std::numeric_limits::max()); - } - - NNGrid(const char* rif, const char* _i) { - if(WriteAccess) { - ERR("Not available in Write mode"); - } + NNGrid() : nodeHelpDesk(NULL) {} + + + NNGrid(const char* rif, const char* _i, NodeInformationHelpDesk* _nodeHelpDesk, StaticGraph* g) : nodeHelpDesk(_nodeHelpDesk), graph(g) { + nodeHelpDesk = _nodeHelpDesk; iif = std::string(_i); + ramIndexTable.resize((1024*1024), std::numeric_limits::max()); ramInFile.open(rif, std::ios::in | std::ios::binary); if(!ramInFile) { ERR(rif << " not found"); } - } - + ~NNGrid() { if(ramInFile.is_open()) ramInFile.close(); -#ifndef ROUTED - if (WriteAccess) { - entries.clear(); - } -#endif if(localStream.get() && localStream->is_open()) { localStream->close(); } @@ -106,7 +100,7 @@ class NNGrid { int slon = edge.lon1; int tlat = 100000*lat2y(edge.lat2/100000.); int tlon = edge.lon2; - AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent ) ); + AddEdge( _GridEdge( edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon), edge.belongsToTinyComponent, edge.mode ) ); } if( 0 == entries.size() ) { ERR("No viable edges for nearest neighbor index. Aborting"); @@ -159,90 +153,7 @@ class NNGrid { return (a == b && c == d) || (a == c && b == d) || (a == d && b == c); } - bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel) { - bool ignoreTinyComponents = (zoomLevel <= 14); -// INFO("Coordinate: " << location << ", zoomLevel: " << zoomLevel << ", ignoring tinyComponentents: " << (ignoreTinyComponents ? "yes" : "no")); -// double time1 = get_timestamp(); - bool foundNode = false; - const _Coordinate startCoord(100000*(lat2y(static_cast(location.lat)/100000.)), location.lon); - /** search for point on edge close to source */ - const unsigned fileIndex = GetFileIndexForLatLon(startCoord.lat, startCoord.lon); - std::vector<_GridEdge> candidates; - const int lowerBoundForLoop = (fileIndex < 32768 ? 0 : -32768); - for(int j = lowerBoundForLoop; (j < (32768+1)) && (fileIndex != UINT_MAX); j+=32768) { - for(int i = -1; i < 2; ++i){ -// unsigned oldSize = candidates.size(); - GetContentsOfFileBucketEnumerated(fileIndex+i+j, candidates); -// INFO("Getting fileIndex=" << fileIndex+i+j << " with " << candidates.size() - oldSize << " candidates"); - } - } -// INFO("looked up " << candidates.size()); - _GridEdge smallestEdge; - _Coordinate tmp, edgeStartCoord, edgeEndCoord; - double dist = std::numeric_limits::max(); - double r, tmpDist; - - BOOST_FOREACH(const _GridEdge & candidate, candidates) { - if(candidate.belongsToTinyComponent && ignoreTinyComponents) - continue; - r = 0.; - tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r); -// INFO("dist " << startCoord << "->[" << candidate.startCoord << "-" << candidate.targetCoord << "]=" << tmpDist ); -// INFO("Looking at edge " << candidate.edgeBasedNode << " at distance " << tmpDist); - if(tmpDist < dist && !DoubleEpsilonCompare(dist, tmpDist)) { -// INFO("a) " << candidate.edgeBasedNode << ", dist: " << tmpDist << ", tinyCC: " << (candidate.belongsToTinyComponent ? "yes" : "no")); - dist = tmpDist; - resultNode.edgeBasedNode = candidate.edgeBasedNode; - resultNode.nodeBasedEdgeNameID = candidate.nameID; - resultNode.weight1 = candidate.weight; - resultNode.weight2 = INT_MAX; - resultNode.location.lat = tmp.lat; - resultNode.location.lon = tmp.lon; - edgeStartCoord = candidate.startCoord; - edgeEndCoord = candidate.targetCoord; - foundNode = true; - smallestEdge = candidate; - //} else if(tmpDist < dist) { - //INFO("a) ignored " << candidate.edgeBasedNode << " at distance " << std::fabs(dist - tmpDist)); - } else if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs(static_cast(candidate.edgeBasedNode)-static_cast(resultNode.edgeBasedNode) ) && CoordinatesAreEquivalent(edgeStartCoord, candidate.startCoord, edgeEndCoord, candidate.targetCoord)) { - resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode); - resultNode.weight2 = candidate.weight; - //INFO("b) " << candidate.edgeBasedNode << ", dist: " << tmpDist); - } - } - - // INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint); - // INFO("length of old edge: " << ApproximateDistance(smallestEdge.startCoord, smallestEdge.targetCoord)); - // INFO("Length of new edge: " << ApproximateDistance(smallestEdge.startCoord, newEndpoint)); - // assert(!resultNode.isBidirected() || (resultNode.weight1 == resultNode.weight2)); - // if(resultNode.weight1 != resultNode.weight2) { - // INFO("-> Weight1: " << resultNode.weight1 << ", weight2: " << resultNode.weight2); - // INFO("-> node: " << resultNode.edgeBasedNode << ", bidir: " << (resultNode.isBidirected() ? "yes" : "no")); - // } - -// INFO("startCoord: " << smallestEdge.startCoord << "; targetCoord: " << smallestEdge.targetCoord << "; newEndpoint: " << resultNode.location); - 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. - if(std::abs(location.lon - resultNode.location.lon) == 1) - resultNode.location.lon = location.lon; - if(std::abs(location.lat - resultNode.location.lat) == 1) - resultNode.location.lat = location.lat; - - resultNode.weight1 *= ratio; - if(INT_MAX != resultNode.weight2) { - resultNode.weight2 *= (1.-ratio); - } - resultNode.ratio = ratio; -// INFO("start: " << edgeStartCoord << ", end: " << edgeEndCoord); -// 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; - } + bool FindPhantomNodeForCoordinate( const _Coordinate & location, PhantomNode & resultNode, const unsigned zoomLevel); bool FindRoutingStarts(const _Coordinate& start, const _Coordinate& target, PhantomNodes & routingStarts, unsigned zoomLevel) { routingStarts.Reset(); @@ -282,7 +193,7 @@ class NNGrid { } -private: +protected: inline unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const { unsigned lineBase = ramIndex/1024; lineBase = lineBase*32*32768; @@ -589,14 +500,30 @@ class NNGrid { std::ofstream indexOutFile; stxxl::vector entries; #endif + NodeInformationHelpDesk* nodeHelpDesk; std::vector ramIndexTable; //8 MB for first level index in RAM std::string iif; + bool writeAccess; + StaticGraph* graph; // LRUCache > cellCache; // LRUCache > fileCache; }; -} -typedef NNGrid::NNGrid ReadOnlyGrid; -typedef NNGrid::NNGrid WritableGrid; +class ReadOnlyGrid : public NNGrid { +public: + ReadOnlyGrid(const char* rif, const char* _i, NodeInformationHelpDesk* _nodeHelpDesk, StaticGraph* g) : NNGrid(rif,_i,_nodeHelpDesk,g) {} +}; + +class WritableGrid : public NNGrid { +public: + WritableGrid() { + ramIndexTable.resize((1024*1024), std::numeric_limits::max()); + } + ~WritableGrid() { + #ifndef ROUTED + entries.clear(); + #endif + } +}; #endif /* NNGRID_H_ */ diff --git a/DataStructures/NodeInformationHelpDesk.h b/DataStructures/NodeInformationHelpDesk.h index 029d30def30..ac920858743 100644 --- a/DataStructures/NodeInformationHelpDesk.h +++ b/DataStructures/NodeInformationHelpDesk.h @@ -32,11 +32,14 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "NNGrid.h" #include "PhantomNodes.h" #include "NodeCoords.h" +#include "TravelMode.h" + +class QueryGraph; class NodeInformationHelpDesk : boost::noncopyable{ public: - NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc) : numberOfNodes(_numberOfNodes), checkSum(crc) { - readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput); + NodeInformationHelpDesk(const char* ramIndexInput, const char* fileIndexInput, const unsigned _numberOfNodes, const unsigned crc, StaticGraph* graph) : numberOfNodes(_numberOfNodes), checkSum(crc) { + readOnlyGrid = new ReadOnlyGrid(ramIndexInput,fileIndexInput, this, graph); assert(0 == coordinateVector.size()); } @@ -64,6 +67,7 @@ class NodeInformationHelpDesk : boost::noncopyable{ origEdgeData_viaNode.resize(numberOfOrigEdges); origEdgeData_nameID.resize(numberOfOrigEdges); origEdgeData_turnInstruction.resize(numberOfOrigEdges); + origEdgeData_mode.resize(numberOfOrigEdges); OriginalEdgeData deserialized_originalEdgeData; for(unsigned i = 0; i < numberOfOrigEdges; ++i) { @@ -71,6 +75,7 @@ class NodeInformationHelpDesk : boost::noncopyable{ origEdgeData_viaNode[i] = deserialized_originalEdgeData.viaNode; origEdgeData_nameID[i] = deserialized_originalEdgeData.nameID; origEdgeData_turnInstruction[i] = deserialized_originalEdgeData.turnInstruction; + origEdgeData_mode[i] = deserialized_originalEdgeData.mode; } edgesInStream.close(); DEBUG("Loaded " << numberOfOrigEdges << " orig edges"); @@ -100,6 +105,10 @@ class NodeInformationHelpDesk : boost::noncopyable{ return origEdgeData_turnInstruction.at(id); } + inline TravelMode getModeFromEdgeID(const unsigned id) const { + return origEdgeData_mode.at(id); + } + inline NodeID getNumberOfNodes() const { return numberOfNodes; } inline NodeID getNumberOfNodes2() const { return coordinateVector.size(); } @@ -128,6 +137,7 @@ class NodeInformationHelpDesk : boost::noncopyable{ std::vector origEdgeData_viaNode; std::vector origEdgeData_nameID; std::vector origEdgeData_turnInstruction; + std::vector origEdgeData_mode; ReadOnlyGrid * readOnlyGrid; const unsigned numberOfNodes; diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h index 2827d7a91bc..57dcba637d6 100644 --- a/DataStructures/PhantomNodes.h +++ b/DataStructures/PhantomNodes.h @@ -22,14 +22,17 @@ or see http://www.gnu.org/licenses/agpl.txt. #define PHANTOMNODES_H_ #include "Coordinate.h" +#include "TravelMode.h" struct PhantomNode { - PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.) {} + PhantomNode() : edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX), ratio(0.), mode1(0), mode2(0) {} NodeID edgeBasedNode; unsigned nodeBasedEdgeNameID; int weight1; int weight2; double ratio; + TravelMode mode1; + TravelMode mode2; _Coordinate location; void Reset() { edgeBasedNode = UINT_MAX; diff --git a/DataStructures/QueryEdge.h b/DataStructures/QueryEdge.h index 3a2aecb82f5..8a9c7a20ca0 100644 --- a/DataStructures/QueryEdge.h +++ b/DataStructures/QueryEdge.h @@ -24,22 +24,32 @@ or see http://www.gnu.org/licenses/agpl.txt. #define QUERYEDGE_H_ #include "TurnInstructions.h" +#include "TravelMode.h" #include "../typedefs.h" #include struct OriginalEdgeData{ - explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t) : viaNode(v), nameID(n), turnInstruction(t) {} + explicit OriginalEdgeData(NodeID v, unsigned n, TurnInstruction t, TravelMode _mode) : viaNode(v), nameID(n), turnInstruction(t), mode(_mode) {} OriginalEdgeData() : viaNode(UINT_MAX), nameID(UINT_MAX), turnInstruction(UCHAR_MAX) {} NodeID viaNode; unsigned nameID; TurnInstruction turnInstruction; + TravelMode mode; }; struct QueryEdge { NodeID source; NodeID target; struct EdgeData { + EdgeData() : + id(0), + shortcut(false), + distance(0), + forward(false), + backward(false) + {} + NodeID id:31; bool shortcut:1; int distance:30; diff --git a/DataStructures/SegmentInformation.h b/DataStructures/SegmentInformation.h index cbe4b81cca2..ff4ca117fc0 100644 --- a/DataStructures/SegmentInformation.h +++ b/DataStructures/SegmentInformation.h @@ -33,10 +33,11 @@ struct SegmentInformation { double bearing; TurnInstruction turnInstruction; bool necessary; - SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec) : - location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec) {} - SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr) : - location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0) {} + char mode; + SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const bool nec, const char mod) : + location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(nec), mode(mod) {} + SegmentInformation(const _Coordinate & loc, const NodeID nam, const double len, const unsigned dur, const TurnInstruction tInstr, const char mod) : + location(loc), nameID(nam), length(len), duration(dur), bearing(0.), turnInstruction(tInstr), necessary(tInstr != 0), mode(mod) {} }; #endif /* SEGMENTINFORMATION_H_ */ diff --git a/DataStructures/TravelMode.h b/DataStructures/TravelMode.h new file mode 100644 index 00000000000..a38e1b6cb7a --- /dev/null +++ b/DataStructures/TravelMode.h @@ -0,0 +1,26 @@ +/* + open source routing machine + Copyright (C) Dennis Luxen, 2010 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU AFFERO General Public License as published by +the Free Software Foundation; either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +or see http://www.gnu.org/licenses/agpl.txt. + */ + +#ifndef TRAVELMODE_H_ +#define TRAVELMODE_H_ + +typedef unsigned char TravelMode; + +#endif /* TRAVELMODE_H_ */ diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp index 46a1d5b824a..aed2dd41a4a 100644 --- a/Descriptors/DescriptionFactory.cpp +++ b/Descriptors/DescriptionFactory.cpp @@ -51,19 +51,20 @@ double DescriptionFactory::GetBearing(const _Coordinate& A, const _Coordinate& B void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) { startPhantom = _startPhantom; - AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1)); + AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1, _startPhantom.mode1)); } void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) { targetPhantom = _targetPhantom; - pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true) ); + pathDescription.push_back(SegmentInformation(_targetPhantom.location, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1, 0, true, _targetPhantom.mode1) ); } void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) { if(1 == pathDescription.size() && pathDescription.back().location == coordinate) { pathDescription.back().nameID = data.nameID; + pathDescription.back().mode = data.mode; } else { - pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) ); + pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction, data.mode) ); } } @@ -83,7 +84,6 @@ void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) { } void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLevel) { - if(0 == pathDescription.size()) return; @@ -170,6 +170,7 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe pathDescription.back().necessary = true; pathDescription.back().turnInstruction = TurnInstructions.NoTurn; targetPhantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->nameID; + targetPhantom.mode1 = (pathDescription.end()-2)->mode; // INFO("Deleting last turn instruction"); } } else { @@ -182,7 +183,8 @@ void DescriptionFactory::Run(const SearchEngineT &sEngine, const unsigned zoomLe pathDescription[0].turnInstruction = TurnInstructions.HeadOn; pathDescription[0].necessary = true; startPhantom.nodeBasedEdgeNameID = pathDescription[0].nameID; - // INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length); + startPhantom.mode1 = pathDescription[0].mode; + // INFO("Deleting first turn instruction, ratio: " << startPhantom.ratio << ", length: " << pathDescription[0].length); } } else { pathDescription[0].duration *= startPhantom.ratio; diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index 72a011b5587..dd0d1142fd9 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -312,7 +312,7 @@ class JSONDescriptor : public BaseDescriptor{ unsigned prefixSumOfNecessarySegments = 0; roundAbout.leaveAtExit = 0; roundAbout.nameID = 0; - std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction; + std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction, tmpMode; //Fetch data from Factory and generate a string from it. BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) { TurnInstruction currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; @@ -358,6 +358,11 @@ class JSONDescriptor : public BaseDescriptor{ reply.content += "\","; intToString(round(segment.bearing), tmpBearing); reply.content += tmpBearing; + + reply.content += ","; + intToString(segment.mode, tmpMode); + reply.content += tmpMode; + reply.content += "]"; segmentVector.push_back( Segment(segment.nameID, segment.length, segmentVector.size() )); diff --git a/Extractor/BaseParser.cpp b/Extractor/BaseParser.cpp index 6981e9570a8..b7b42cb101a 100644 --- a/Extractor/BaseParser.cpp +++ b/Extractor/BaseParser.cpp @@ -25,6 +25,7 @@ extractor_callbacks(ec), scriptingEnvironment(se), luaState(NULL), use_turn_rest luaState = se.getLuaStateForThreadID(0); ReadUseRestrictionsSetting(); ReadRestrictionExceptions(); + ReadModes(); } void BaseParser::ReadUseRestrictionsSetting() { @@ -64,6 +65,28 @@ void BaseParser::ReadRestrictionExceptions() { } } +void BaseParser::ReadModes() { + if(lua_function_exists(luaState, "get_modes" )) { + //get list of modes + try { + luabind::call_function( + luaState, + "get_modes", + boost::ref(modes) + ); + BOOST_FOREACH(std::string & str, modes) { + INFO("mode found: " << str); + } + } catch (const luabind::error &er) { + lua_State* Ler=er.state(); + report_errors(Ler, -1); + ERR(er.what()); + } + } else { + INFO("Found no modes"); + } +} + void BaseParser::report_errors(lua_State *L, const int status) const { if( 0!=status ) { std::cerr << "-- " << lua_tostring(L, -1) << std::endl; diff --git a/Extractor/BaseParser.h b/Extractor/BaseParser.h index 6a19efa0756..8ed7bf228cb 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -46,6 +46,7 @@ class BaseParser : boost::noncopyable { protected: virtual void ReadUseRestrictionsSetting(); virtual void ReadRestrictionExceptions(); + virtual void ReadModes(); virtual bool ShouldIgnoreRestriction(const std::string& except_tag_string) const; ExtractorCallbacks* extractor_callbacks; @@ -53,7 +54,7 @@ class BaseParser : boost::noncopyable { lua_State* luaState; std::vector restriction_exceptions; bool use_turn_restrictions; - + std::vector modes; }; #endif /* BASEPARSER_H_ */ diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index b2476bc8685..a7e6d99347e 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -231,9 +231,6 @@ 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 ExtractionWay::notSure: - fout.write((char*)&zero, sizeof(short)); - break; case ExtractionWay::oneway: fout.write((char*)&one, sizeof(short)); break; @@ -250,13 +247,11 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const break; } fout.write((char*)&intWeight, sizeof(int)); - assert(edgeIT->type >= 0); - fout.write((char*)&edgeIT->type, sizeof(short)); fout.write((char*)&edgeIT->nameID, sizeof(unsigned)); 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)); + fout.write((char*)&edgeIT->mode, sizeof(unsigned char)); } ++usedEdgeCounter; ++edgeIT; @@ -265,6 +260,8 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const std::cout << "ok, after " << get_timestamp() - time << "s" << std::endl; std::cout << "[extractor] setting number of edges ... " << std::flush; + std::cout << "[extractor] number of edges: " << usedEdgeCounter << std::flush; + fout.seekp(positionInFile); fout.write((char*)&usedEdgeCounter, sizeof(unsigned)); fout.close(); diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index c8b5fc1aa59..ccbbd6ed290 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -64,18 +64,21 @@ bool ExtractorCallbacks::restrictionFunction(const _RawRestrictionContainer &r) /** warning: caller needs to take care of synchronization! */ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { - if((0 < parsed_way.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile + if((0 < parsed_way.forward.speed) || (0 < parsed_way.backward.speed) || (0 < parsed_way.duration)) { //Only true if the way is specified by the speed profile if(UINT_MAX == parsed_way.id){ DEBUG("found bogus way with id: " << parsed_way.id << " of size " << parsed_way.path.size()); return; } - + if(0 < parsed_way.duration) { //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); + parsed_way.forward.speed = parsed_way.duration/(parsed_way.path.size()-1); + parsed_way.backward.speed = parsed_way.duration/(parsed_way.path.size()-1); } - if(FLT_EPSILON >= fabs(-1. - parsed_way.speed)){ + if( ((0= fabs(-1. - parsed_way.forward.speed))) || + ((0= fabs(-1. - parsed_way.backward.speed))) + ) { DEBUG("found way with bogus speed, id: " << parsed_way.id); return; } @@ -90,53 +93,54 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { parsed_way.nameID = string_map_iterator->second; } - if(ExtractionWay::opposite == parsed_way.direction) { - std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); - parsed_way.direction = ExtractionWay::oneway; - } - - const 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(parsed_way.path.back()); - - //The following information is needed to identify start and end segments of restrictions - 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())); - } - } + bool split = parsed_way.IsBidirectional() && parsed_way.HasDiffDirections(); + + if( !parsed_way.IsOpposite() ) { + 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], + (split ? ExtractionWay::oneway : parsed_way.Direction()), + parsed_way.forward.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.HasDuration(), + parsed_way.isAccessRestricted, + parsed_way.forward.mode + ) + ); + } + //used to identify start and end segments of restrictions + 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( parsed_way.IsOpposite() || 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], + ExtractionWay::oneway, + parsed_way.backward.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + parsed_way.HasDuration(), + parsed_way.isAccessRestricted, + parsed_way.backward.mode + ) + ); + } + //used to identify start and end segments of restrictions + 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())); + } + + //store node ids + for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { + externalMemory->usedNodeIDs.push_back(parsed_way.path[n]); + } + externalMemory->usedNodeIDs.push_back(parsed_way.path.back()); + + } } diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index fe21da957db..6f2b9a47ee4 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -35,47 +35,82 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../DataStructures/NodeCoords.h" #include "../DataStructures/Restriction.h" #include "../DataStructures/TimingUtil.h" +#include "../DataStructures/TravelMode.h" #include "../typedefs.h" typedef boost::unordered_map StringMap; typedef boost::unordered_map > StringToIntPairMap; + struct ExtractionWay { - ExtractionWay() { - Clear(); - } - - inline void Clear(){ - id = UINT_MAX; - nameID = UINT_MAX; - path.clear(); - keyVals.EraseAll(); - direction = ExtractionWay::notSure; - speed = -1; - backward_speed = -1; - duration = -1; - type = -1; - access = true; - roundabout = false; - isAccessRestricted = false; - ignoreInGrid = false; - } + struct SettingsForDirection { + SettingsForDirection() : speed(-1), mode(0) {} + + double speed; + TravelMode mode; + }; + + ExtractionWay() : + id(UINT_MAX), + nameID(UINT_MAX), + duration(-1), + access(true), + roundabout(false), + isAccessRestricted(false), + ignoreInGrid(false) { + path.clear(); + keyVals.EraseAll(); + } + enum Directions { - notSure = 0, oneway, bidirectional, opposite + oneway, bidirectional, opposite }; - Directions direction; + + inline bool HasDuration() { return duration>0; } + inline bool IsBidirectional() { return forward.mode!=0 && backward.mode!=0; } + inline bool IsOneway() { return forward.mode!=0 && backward.mode==0; } + inline bool IsOpposite() { return forward.mode==0 && backward.mode!=0; } + inline bool HasDiffDirections() { return (forward.mode != backward.mode) || (forward.speed != backward.speed); } + inline Directions Direction() { + if( IsOneway() ) { + return ExtractionWay::oneway; + } + if( IsOpposite() ) { + return ExtractionWay::opposite; + } + return ExtractionWay::bidirectional; + } + + inline void set_mode(const TravelMode m) { forward.mode = m; backward.mode = m; } + inline const TravelMode get_mode() { + if( forward.mode == backward.mode ) { + return forward.mode; + } else { + return -1; + } + } + + inline void set_speed(const double s) { forward.speed = s; backward.speed = s; } + inline const double get_speed() { + if( forward.speed == backward.speed ) { + return forward.speed; + } else { + return -1; + } + } + + unsigned id; unsigned nameID; std::string name; - double speed; - double backward_speed; double duration; - short type; bool access; bool roundabout; bool isAccessRestricted; bool ignoreInGrid; + SettingsForDirection forward; + SettingsForDirection backward; std::vector< NodeID > path; HashTable keyVals; }; @@ -89,18 +124,12 @@ struct ExtractorRelation { }; 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); - } + InternalExtractorEdge() : start(0), target(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), mode(0) {}; + InternalExtractorEdge(NodeID s, NodeID t) : start(s), target(t), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {} + InternalExtractorEdge(NodeID s, NodeID t, short d, double sp): start(s), target(t), direction(d), speed(sp), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false) {} + InternalExtractorEdge(NodeID s, NodeID t, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, TravelMode _mode): start(s), target(t), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), mode(_mode) {} NodeID start; NodeID target; - short type; short direction; double speed; unsigned nameID; @@ -108,8 +137,8 @@ struct InternalExtractorEdge { bool ignoreInGrid; bool isDurationSet; bool isAccessRestricted; - bool isContraFlow; - + TravelMode mode; + _Coordinate startCoord; _Coordinate targetCoord; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 6405802f8cd..8401b2dfa3f 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -292,12 +292,11 @@ inline void PBFParser::parseRelation(_ThreadData * threadData) { } inline void PBFParser::parseWay(_ThreadData * threadData) { - ExtractionWay w; std::vector waysToParse; const int number_of_ways = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); waysToParse.reserve(number_of_ways); for(int i = 0; i < number_of_ways; ++i) { - w.Clear(); + ExtractionWay w; const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); w.id = inputWay.id(); unsigned pathNode(0); @@ -319,7 +318,7 @@ inline void PBFParser::parseWay(_ThreadData * threadData) { #pragma omp parallel for schedule ( guided ) for(int i = 0; i < number_of_ways; ++i) { ExtractionWay & w = waysToParse[i]; - ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); + ParseWayInLua( w, scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()) ); } BOOST_FOREACH(ExtractionWay & w, waysToParse) { diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index 6bab21c5f0c..509c5f096c4 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -68,24 +68,24 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { luabind::class_("Way") .def(luabind::constructor<>()) .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), - luabind::value("oneway", 1), - luabind::value("bidirectional", 2), - luabind::value("opposite", 3) - ] + .def_readwrite("forward", &ExtractionWay::forward) + .def_readwrite("backward", &ExtractionWay::backward) + .property("mode", &ExtractionWay::get_mode, &ExtractionWay::set_mode) + .property("speed", &ExtractionWay::get_speed, &ExtractionWay::set_speed) ]; + + luabind::module(myLuaState) [ + luabind::class_("WaySettingsForDirection") + .def_readwrite("speed", &ExtractionWay::SettingsForDirection::speed) + .def_readwrite("mode", &ExtractionWay::SettingsForDirection::mode) + ]; + luabind::module(myLuaState) [ luabind::class_ >("vector") .def("Add", &std::vector::push_back) diff --git a/Plugins/RawRouteData.h b/Plugins/RawRouteData.h index f0c105486dc..0a7fde780b4 100644 --- a/Plugins/RawRouteData.h +++ b/Plugins/RawRouteData.h @@ -24,11 +24,12 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../typedefs.h" struct _PathData { - _PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { } + _PathData(NodeID no, unsigned na, unsigned tu, unsigned dur, const TravelMode _mode) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu), mode(_mode) { } NodeID node; unsigned nameID; unsigned durationOfSegment; short turnInstruction; + TravelMode mode; }; struct RawRouteData { diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h index 4cd256b9819..b53abb64058 100644 --- a/RoutingAlgorithms/AlternativePathRouting.h +++ b/RoutingAlgorithms/AlternativePathRouting.h @@ -56,7 +56,7 @@ class AlternativeRouting : private BasicRoutingInterface { ~AlternativeRouting() {} - void operator()(const PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) { + void operator()(PhantomNodes & phantomNodePair, RawRouteData & rawRouteData) { if(!phantomNodePair.AtLeastOnePhantomNodeIsUINTMAX() || phantomNodePair.PhantomNodesHaveEqualLocation()) { rawRouteData.lengthOfShortestPath = rawRouteData.lengthOfAlternativePath = INT_MAX; return; @@ -181,6 +181,12 @@ class AlternativeRouting : private BasicRoutingInterface { //Unpack shortest path and alternative, if they exist if(INT_MAX != upper_bound_to_shortest_path_distance) { + // set mode of first instruction + // if the best route started from the opposite edge, use mode2 rather than mode1 + if( packedShortestPath.front() == phantomNodePair.startPhantom.edgeBasedNode+1 ) { + phantomNodePair.startPhantom.mode1 = phantomNodePair.startPhantom.mode2; + } + super::UnpackPath(packedShortestPath, rawRouteData.computedShortestPath); rawRouteData.lengthOfShortestPath = upper_bound_to_shortest_path_distance; } else { diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index f329c697bd3..5a73ec26e26 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -101,7 +101,7 @@ class BasicRoutingInterface : boost::noncopyable{ } } - inline void UnpackPath(const std::vector & packedPath, std::vector<_PathData> & unpackedPath) const { + inline void UnpackPath(const std::vector & packedPath, std::vector<_PathData> & unpackedPath) const { const unsigned sizeOfPackedPath = packedPath.size(); std::stack > recursionStack; @@ -144,7 +144,7 @@ class BasicRoutingInterface : boost::noncopyable{ recursionStack.push(std::make_pair(edge.first, middle)); } else { assert(!ed.shortcut); - unpackedPath.push_back(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance) ); + unpackedPath.push_back(_PathData(ed.id, _queryData.nodeHelpDesk->getNameIndexFromEdgeID(ed.id), _queryData.nodeHelpDesk->getTurnInstructionFromEdgeID(ed.id), ed.distance, _queryData.nodeHelpDesk->getModeFromEdgeID(ed.id)) ); } } } @@ -158,9 +158,12 @@ class BasicRoutingInterface : boost::noncopyable{ edge = recursionStack.top(); recursionStack.pop(); + typename QueryDataT::Graph::EdgeIterator smallestEdge = SPECIAL_EDGEID; int smallestWeight = INT_MAX; for(typename QueryDataT::Graph::EdgeIterator eit = _queryData.graph->BeginEdges(edge.first);eit < _queryData.graph->EndEdges(edge.first);++eit){ + + const int weight = _queryData.graph->GetEdgeData(eit).distance; if(_queryData.graph->GetTarget(eit) == edge.second && weight < smallestWeight && _queryData.graph->GetEdgeData(eit).forward){ smallestEdge = eit; diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h index 66d374079a3..f893c80dbfe 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -69,7 +69,7 @@ class ShortestPathRouting : public BasicRoutingInterface{ middle1 = UINT_MAX; middle2 = UINT_MAX; - + //insert new starting nodes into forward heap, adjusted by previous distances. if(searchFrom1stStartNode) { forward_heap1.Insert(phantomNodePair.startPhantom.edgeBasedNode, -phantomNodePair.startPhantom.weight1, phantomNodePair.startPhantom.edgeBasedNode); @@ -165,7 +165,7 @@ class ShortestPathRouting : public BasicRoutingInterface{ if(*(packedPath1.end()-1) != *(temporaryPackedPath1.begin())) { packedPath1.swap(packedPath2); std::swap(distance1, distance2); - } + } } } packedPath1.insert(packedPath1.end(), temporaryPackedPath1.begin(), temporaryPackedPath1.end()); @@ -185,9 +185,17 @@ class ShortestPathRouting : public BasicRoutingInterface{ if(distance1 > distance2){ std::swap(packedPath1, packedPath2); } + + // set mode of first instruction + // if the best route started from the opposite edge, use mode2 rather than mode1 + if( packedPath1.front() == phantomNodesVector[0].startPhantom.edgeBasedNode+1 ) { + phantomNodesVector[0].startPhantom.mode1 = phantomNodesVector[0].startPhantom.mode2; + } + remove_consecutive_duplicates_from_vector(packedPath1); super::UnpackPath(packedPath1, rawRouteData.computedShortestPath); rawRouteData.lengthOfShortestPath = std::min(distance1, distance2); + return; } }; diff --git a/Server/DataStructures/QueryObjectsStorage.cpp b/Server/DataStructures/QueryObjectsStorage.cpp index 325cdb97de5..6a5e17e844f 100644 --- a/Server/DataStructures/QueryObjectsStorage.cpp +++ b/Server/DataStructures/QueryObjectsStorage.cpp @@ -21,6 +21,8 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "QueryObjectsStorage.h" #include "../../Util/GraphLoader.h" +#include "../../DataStructures/QueryEdge.h" +#include "../../DataStructures/StaticGraph.h" QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIndexPath, std::string fileIndexPath, std::string nodesPath, std::string edgesPath, std::string namesPath, std::string timestampPath) { INFO("loading graph data"); @@ -55,7 +57,7 @@ QueryObjectsStorage::QueryObjectsStorage(std::string hsgrPath, std::string ramIn if(!nodesInStream) { ERR(nodesPath << " not found"); } std::ifstream edgesInStream(edgesPath.c_str(), std::ios::binary); if(!edgesInStream) { ERR(edgesPath << " not found"); } - nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n, checkSum); + nodeHelpDesk = new NodeInformationHelpDesk(ramIndexPath.c_str(), fileIndexPath.c_str(), n, checkSum, graph); nodeHelpDesk->initNNGrid(nodesInStream, edgesInStream); //deserialize street name list diff --git a/Server/DataStructures/QueryObjectsStorage.h b/Server/DataStructures/QueryObjectsStorage.h index be8bba073ec..28f82c2700c 100644 --- a/Server/DataStructures/QueryObjectsStorage.h +++ b/Server/DataStructures/QueryObjectsStorage.h @@ -26,8 +26,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include "../../DataStructures/NodeInformationHelpDesk.h" -#include "../../DataStructures/QueryEdge.h" -#include "../../DataStructures/StaticGraph.h" struct QueryObjectsStorage { typedef StaticGraph QueryGraph; diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index 66401548c8c..2e7fe8ad230 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -98,23 +98,22 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL edgeList.reserve(m); EdgeWeight weight; - short type; NodeID nameID; int length; - bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow; - + bool isRoundabout, ignoreInGrid, isAccessRestricted; + TravelMode mode; + for (EdgeID i=0; i 0, "loaded null length edge" ); GUARANTEE(weight > 0, "loaded null weight"); @@ -125,8 +124,6 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL if (1 == dir) { backward = false; } if (2 == dir) { forward = false; } - assert(type >= 0); - // translate the external NodeIDs to internal IDs ExternalNodeMap::iterator intNodeID = ext2IntNodeMap.find(source); if( ext2IntNodeMap.find(source) == ext2IntNodeMap.end()) { @@ -150,8 +147,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL std::swap(source, target); std::swap(forward, backward); } - - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow ); + + EdgeT inputEdge(source, target, nameID, weight, forward, backward, isRoundabout, ignoreInGrid, isAccessRestricted, mode ); edgeList.push_back(inputEdge); } std::sort(edgeList.begin(), edgeList.end()); @@ -211,7 +208,6 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector& edgeList, s for (EdgeID i=0; i> source >> target >> length >> dir >> speedType; @@ -295,7 +291,7 @@ NodeID readDTMPGraphFromStream(std::istream &in, std::vector& edgeList, s if(source == UINT_MAX || target == UINT_MAX) { ERR("nonexisting source or target" ); } - EdgeT inputEdge(source, target, 0, weight, forward, backward, type ); + EdgeT inputEdge(source, target, 0, weight, forward, backward ); edgeList.push_back(inputEdge); } ext2IntNodeMap.clear(); @@ -367,7 +363,6 @@ unsigned readHSGRFromStream(std::istream &in, std::vector& nodeList, std: in.read((char*) &numberOfEdges, sizeof(unsigned)); edgeList.resize(numberOfEdges); in.read((char*) &(edgeList[0]), numberOfEdges*sizeof(EdgeT)); - return numberOfNodes; } diff --git a/createHierarchy.cpp b/createHierarchy.cpp index 7156cef3224..d994caad88c 100644 --- a/createHierarchy.cpp +++ b/createHierarchy.cpp @@ -255,6 +255,7 @@ int main (int argc, char *argv[]) { ERR("Failed at edges of node " << node << " of " << numberOfNodes); } //Serialize edges + //INFO( "createHierachy write, i: " << usedEdgeCounter << ", mode: " << (long)currentEdge.data.mode ); edgeOutFile.write((char*) ¤tEdge, sizeof(StaticGraph::_StrEdge)); ++edge; ++usedEdgeCounter; diff --git a/features/bicycle/cycleway.feature b/features/bicycle/cycleway.feature index f260294539d..b1cba1ad383 100644 --- a/features/bicycle/cycleway.feature +++ b/features/bicycle/cycleway.feature @@ -78,4 +78,4 @@ Reference: http://wiki.openstreetmap.org/wiki/Key:cycleway | motorway | lane | yes | x | | residential | lane | yes | x | | footway | lane | yes | x | - | cycleway | lane | yes | x | + | cycleway | lane | yes | x | \ No newline at end of file diff --git a/features/bicycle/mode.feature b/features/bicycle/mode.feature index c24af4686cb..e6c94c11c74 100644 --- a/features/bicycle/mode.feature +++ b/features/bicycle/mode.feature @@ -1,10 +1,15 @@ @routing @bicycle @mode Feature: Bike - Mode flag +# bicycle modes: +# 1 bike +# 2 pushing +# 3 ferry +# 4 train + Background: Given the profile "bicycle" - @todo Scenario: Bike - Mode when using a ferry Given the node map | a | b | | @@ -17,15 +22,34 @@ Feature: Bike - Mode flag | cd | primary | | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left, destination | bike,ferry,bike | - | d | a | cd,bc,ab | head,right,left, destination | bike,ferry,bike | - | c | a | bc,ab | head,left,destination | ferry,bike | - | d | b | cd,bc | head,right,destination | bike,ferry | - | a | c | ab,bc | head,right,destination | bike,ferry | - | b | d | bc,cd | head,left,destination | ferry,bike | - - @todo + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,3,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,3,1 | + | c | a | bc,ab | head,left,destination | 3,1 | + | d | b | cd,bc | head,right,destination | 1,3 | + | a | c | ab,bc | head,right,destination | 1,3 | + | b | d | bc,cd | head,left,destination | 3,1 | + + Scenario: Bike - Mode when using a train + Given the node map + | a | b | | + | | c | d | + + And the ways + | nodes | highway | railway | bicycle | + | ab | primary | | | + | bc | | train | yes | + | cd | primary | | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,4,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,4,1 | + | c | a | bc,ab | head,left,destination | 4,1 | + | d | b | cd,bc | head,right,destination | 1,4 | + | a | c | ab,bc | head,right,destination | 1,4 | + | b | d | bc,cd | head,left,destination | 4,1 | + Scenario: Bike - Mode when pushing bike against oneways Given the node map | a | b | | @@ -38,15 +62,14 @@ Feature: Bike - Mode flag | cd | primary | | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left,destination | bike,push,bike | - | d | a | cd,bc,ab | head,right,left,destination | bike,push,bike | - | c | a | bc,ab | head,left,destination | push,bike | - | d | b | cd,bc | head,right,destination | bike,push | - | a | c | ab,bc | head,right,destination | bike,push | - | b | d | bc,cd | head,left,destination | push,bike | - - @todo + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,1,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,1 | + | b | d | bc,cd | head,left,destination | 1,1 | + Scenario: Bike - Mode when pushing on pedestrain streets Given the node map | a | b | | @@ -59,15 +82,14 @@ Feature: Bike - Mode flag | cd | primary | When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left,destination | bike,push,bike | - | d | a | cd,bc,ab | head,right,left,destination | bike,push,bike | - | c | a | bc,ab | head,left,destination | push,bike | - | d | b | cd,bc | head,right,destination | bike,push | - | a | c | ab,bc | head,right,destination | bike,push | - | b | d | bc,cd | head,left,destination | push,bike | - - @todo + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + Scenario: Bike - Mode when pushing on pedestrain areas Given the node map | a | b | | | @@ -80,10 +102,50 @@ Feature: Bike - Mode flag | df | primary | | When I route I should get - | from | to | route | modes | - | a | f | ab,bcd,df | bike,push,bike | - | f | a | df,bcd,ab | bike,push,bike | - | d | a | bcd,ab | push,bike | - | f | b | df,bcd | bike,push | - | a | d | ab,bcd | bike,push | - | b | f | bcd,df | push,bike | + | from | to | route | modes | + | a | f | ab,bcd,df | 1,2,1 | + | f | a | df,bcd,ab | 1,2,1 | + | d | a | bcd,ab | 2,1 | + | f | b | df,bcd | 1,2 | + | a | d | ab,bcd | 1,2 | + | b | f | bcd,df | 2,1 | + + Scenario: Bike - Mode when pushing on steps + Given the node map + | a | b | | | + | | c | d | f | + + And the ways + | nodes | highway | + | ab | primary | + | bc | steps | + | cd | primary | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + + Scenario: Bike - Mode when bicycle=dismount + Given the node map + | a | b | | | + | | c | d | f | + + And the ways + | nodes | highway | bicycle | + | ab | primary | | + | bc | primary | dismount | + | cd | primary | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 13590d07bbd..951f78150f0 100644 --- a/features/bicycle/pushing.feature +++ b/features/bicycle/pushing.feature @@ -98,11 +98,11 @@ Feature: Bike - Accessability of different way types | cd | primary | | When I route I should get - | from | to | route | turns | - | a | d | ab,bc,cd | head,right,left,destination | - | d | a | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination | - | c | a | bc,ab | head,leave_contraflow,destination | - | d | b | cd,bc | head,enter_contraflow,destination | + | from | to | route | turns | + | a | d | ab,bc,cd | head,right,left,destination | + | d | a | cd,bc,ab | head,right,left,destination | + | c | a | bc,ab | head,left,destination | + | d | b | cd,bc | head,right,destination | @todo Scenario: Bike - Instructions when pushing bike on footway/pedestrian, etc. @@ -117,8 +117,22 @@ Feature: Bike - Accessability of different way types | cd | primary | When I route I should get - | from | to | route | turns | - | a | d | ab,bc,cd | head,right,left,destination | - | d | a | cd,bc,ab | head,enter_contraflow,leave_contraflow,destination | - | c | a | bc,ab | head,leave_contraflow,destination | - | d | b | cd,bc | head,enter_contraflow,destination | \ No newline at end of file + | from | to | route | turns | + | a | d | ab,bc,cd | head,right,left,destination | + | d | a | cd,bc,ab | head,right,left,destination | + | c | a | bc,ab | head,left,destination | + | d | b | cd,bc | head,right,destination | + + Scenario: Bike - Push bikes on pedestrian areas + Given the node map + | a | b | c | d | + + And the ways + | nodes | highway | + | ab | primary | + | bc | pedestrian | + | cd | primary | + + When I route I should get + | from | to | route | turns | + | a | d | ab,bc,cd | head,straight,straight,destination | diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index 13c8b6a0417..581bb39c43f 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -64,20 +64,20 @@ got['distance'] = instructions ? "#{json['route_summary']['total_distance'].to_s}m" : '' end if table.headers.include?('time') - raise "*** Time must be specied in seconds. (ex: 60s)" unless row['time'] =~ /\d+s/ + raise "*** Time must be specied in seconds. (ex: 60s)" unless row['time']=='' || row['time'] =~ /\d+s/ got['time'] = instructions ? "#{json['route_summary']['total_time'].to_s}s" : '' end if table.headers.include? 'bearing' - got['bearing'] = bearings + got['bearing'] = instructions ? bearings : '' end if table.headers.include? 'compass' - got['compass'] = compasses + got['compass'] = instructions ? compasses : '' end if table.headers.include? 'turns' - got['turns'] = turns + got['turns'] = instructions ? turns : '' end if table.headers.include? 'modes' - got['modes'] = modes + got['modes'] = instructions ? modes : '' end if table.headers.include? '#' # comment column got['#'] = row['#'] # copy value so it always match diff --git a/features/support/route.rb b/features/support/route.rb index 9cfbbfa14dd..73a4a06621f 100644 --- a/features/support/route.rb +++ b/features/support/route.rb @@ -118,9 +118,7 @@ def turn_list instructions 12 => :leave_roundabout, 13 => :stay_roundabout, 14 => :start_end_of_street, - 15 => :destination, - 16 => :enter_contraflow, - 17 => :leave_contraflow + 15 => :destination } instructions. map { |r| types[r[0].to_i].to_s }. diff --git a/features/testbot/graph.feature b/features/testbot/graph.feature index 97a51711974..c0a55996373 100644 --- a/features/testbot/graph.feature +++ b/features/testbot/graph.feature @@ -5,7 +5,6 @@ Test the input data descibed on https://github.com/DennisOSRM/Project-OSRM/wiki/ Background: Given the profile "testbot" - @smallest Scenario: Graph transformation Given the node map | | | d | diff --git a/features/testbot/mode.feature b/features/testbot/mode.feature index 3192c48f9b1..faa542d2698 100644 --- a/features/testbot/mode.feature +++ b/features/testbot/mode.feature @@ -1,26 +1,146 @@ @routing @testbot @mode Feature: Testbot - Mode flag - Background: - Given the profile "testbot" +# testbot modes: +# 1 normal +# 2 route +# 3 river downstream +# 4 river upstream +# 5 steps down +# 6 steps up + + Background: + Given the profile "testbot" + + Scenario: Testbot - Mode for routes + Given the node map + | a | b | | | | + | | c | d | e | f | + + And the ways + | nodes | highway | route | duration | + | ab | primary | | | + | bc | | ferry | 0:01 | + | cd | primary | | | + | de | primary | | | + | ef | primary | | | + + When I route I should get + | from | to | route | turns | modes | + | a | d | ab,bc,cd | head,right,left,destination | 1,2,1 | + | d | a | cd,bc,ab | head,right,left,destination | 1,2,1 | + | c | a | bc,ab | head,left,destination | 2,1 | + | d | b | cd,bc | head,right,destination | 1,2 | + | a | c | ab,bc | head,right,destination | 1,2 | + | b | d | bc,cd | head,left,destination | 2,1 | + | a | f | ab,bc,cd,de,ef | head,right,left,straight,straight,destination | 1,2,1,1,1 | + + Scenario: Testbot - Modes for each direction + Given the node map + | | | | | | | d | + | | | | | | 2 | | + | | | | | 6 | | 5 | + | a | 0 | b | c | | | | + | | | | | 4 | | 1 | + | | | | | | 3 | | + | | | | | | | e | + + And the ways + | nodes | highway | oneway | + | abc | primary | | + | cd | primary | yes | + | ce | river | | + | de | primary | | + + When I route I should get + | from | to | route | modes | + | 0 | 1 | abc,ce,de | 1,3,1 | + | 1 | 0 | de,ce,abc | 1,4,1 | + | 0 | 2 | abc,cd | 1,1 | + | 2 | 0 | cd,de,ce,abc | 1,1,4,1 | + | 0 | 3 | abc,ce | 1,3 | + | 3 | 0 | ce,abc | 4,1 | + | 4 | 3 | ce | 3 | + | 3 | 4 | ce | 4 | + | 3 | 1 | ce,de | 3,1 | + | 1 | 3 | de,ce | 1,4 | + | a | e | abc,ce | 1,3 | + | e | a | ce,abc | 4,1 | + | a | d | abc,cd | 1,1 | + | d | a | de,ce,abc | 1,4,1 | - @todo - Scenario: Bike - Mode - Given the node map - | a | b | | - | | c | d | - - And the ways - | nodes | highway | route | duration | - | ab | primary | | | - | bc | | ferry | 0:01 | - | cd | primary | | | - - When I route I should get - | from | to | route | turns | modes | - | a | d | ab,bc,cd | head,right,left,destination | bot,ferry,bot | - | d | a | cd,bc,ab | head,right left,destination | bot,ferry,bot | - | c | a | bc,ab | head,left,destination | ferry,bot | - | d | b | cd,bc | head,right,destination | bot,ferry | - | a | c | ab,bc | head,right,destination | bot,ferry | - | b | d | bc,cd | head,left,destination | ferry,bot | + Scenario: Testbot - Modes in each direction (simple) + Given the node map + | | 0 | 1 | | + | a | | | b | + + And the ways + | nodes | highway | oneway | + | ab | river | | + + When I route I should get + | from | to | route | modes | + | 0 | 1 | ab | 3 | + | 1 | 0 | ab | 4 | + + Scenario: Testbot - Modes in each direction (same speed in both direction) + Given the node map + | | 0 | 1 | | + | a | | | b | + + And the ways + | nodes | highway | + | ab | steps | + + When I route I should get + | from | to | route | modes | time | + | 0 | 1 | ab | 5 | 60s +-1 | + | 1 | 0 | ab | 6 | 60s +-1 | + + Scenario: Testbot - Modes for opposite direction + Given the node map + | | 0 | 1 | | + | a | | | b | + + And the ways + | nodes | highway | oneway | + | ab | steps | -1 | + + When I route I should get + | from | to | route | modes | + | 0 | 1 | | | + | 1 | 0 | ab | 6 | + + @via + Scenario: Testbot - Modes and via point at dead end + Given the node map + | a | b | c | + | | d | | + + And the ways + | nodes | highway | + | abc | primary | + | bd | steps | + + When I route I should get + | waypoints | route | modes | + | a,d,c | abc,bd,bd,abc | 1,5,6,1 | + | c,d,a | abc,bd,bd,abc | 1,5,6,1 | + + @via + Scenario: Testbot - Modes and via point at river + Given the node map + | | | 0 | | | + | a | b | | c | d | + + + And the ways + | nodes | highway | + | ab | primary | + | bc | river | + | cd | primary | + + When I route I should get + | waypoints | route | modes | + | a,0,d | ab,bc,cd | 1,3,1 | + | d,0,a | cd,bc,ab | 1,4,1 | diff --git a/profile.lua b/profile.lua index 33a7247d668..2089ed2683a 100644 --- a/profile.lua +++ b/profile.lua @@ -206,7 +206,6 @@ function way_function (way) if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then way.ignore_in_grid = true end - way.type = 1 return 1 end diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 98d03c83d28..6e232920a94 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -1,4 +1,5 @@ require("lib/access") +require("lib/maxspeed") -- Begin of globals barrier_whitelist = { [""] = true, ["cycle_barrier"] = true, ["bollard"] = true, ["entrance"] = true, ["cattle_grid"] = true, ["border_control"] = true, ["toll_booth"] = true, ["sally_port"] = true, ["gate"] = true, ["no"] = true} @@ -95,6 +96,13 @@ turn_penalty = 60 turn_bias = 1.4 -- End of globals +--modes +mode_normal = 1 +mode_pushing = 2 +mode_ferry = 3 +mode_train = 4 + + function get_exceptions(vector) for i,v in ipairs(restriction_exception_tags) do vector:Add(v) @@ -126,7 +134,7 @@ function node_function (node) end end - return 1 + return true end function way_function (way) @@ -144,18 +152,18 @@ function way_function (way) (not man_made or man_made=='') and (not public_transport or public_transport=='') then - return 0 + return false end -- don't route on ways or railways that are still under construction if highway=='construction' or railway=='construction' then - return 0 + return false end -- access local access = Access.find_access_tag(way, access_tags_hierachy) if access_tag_blacklist[access] then - return 0 + return false end @@ -177,6 +185,9 @@ function way_function (way) local area = way.tags:Find("area") local foot = way.tags:Find("foot") local surface = way.tags:Find("surface") + local foot_forward = way.tags:Find("foot:forward") + local foot_backward = way.tags:Find("foot:backward") + local bicycle = way.tags:Find("bicycle") -- name if "" ~= ref and "" ~= name then @@ -190,156 +201,147 @@ function way_function (way) -- this encoding scheme is excepted to be a temporary solution end + way.mode = mode_normal + -- speed if route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) - way.direction = Way.bidirectional + way.mode = mode_ferry way.ignore_in_grid = true if durationIsValid(duration) then way.duration = math.max( 1, parseDuration(duration) ) else way.speed = route_speeds[route] end - elseif railway and platform_speeds[railway] then + elseif platform_speeds[railway] then -- railway platforms (old tagging scheme) way.speed = platform_speeds[railway] elseif platform_speeds[public_transport] then -- public_transport platforms (new tagging platform) way.speed = platform_speeds[public_transport] - elseif railway and railway_speeds[railway] then + elseif railway_speeds[railway] then -- railways if access and access_tag_whitelist[access] then + way.mode = mode_train way.speed = railway_speeds[railway] - way.direction = Way.bidirectional end - elseif amenity and amenity_speeds[amenity] then + elseif amenity_speeds[amenity] then -- parking areas way.speed = amenity_speeds[amenity] elseif bicycle_speeds[highway] then -- regular ways way.speed = bicycle_speeds[highway] - elseif access and access_tag_whitelist[access] then + elseif 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] + way.mode = mode_pushing elseif man_made and man_made_speeds[man_made] then -- man made structures way.speed = man_made_speeds[man_made] + way.mode = mode_pushing elseif foot == 'yes' then way.speed = walking_speed + way.mode = mode_pushing + elseif foot_forward == 'yes' then + way.forward.speed = walking_speed + way.forward.mode = mode_pushing + way.backward.mode = 0 + elseif foot_backward == 'yes' then + way.backward.speed = walking_speed + way.backward.mode = mode_pushing + way.forward.mode = 0 end end end -- direction - way.direction = Way.bidirectional local impliedOneway = false if junction == "roundabout" or highway == "motorway_link" or highway == "motorway" then - way.direction = Way.oneway impliedOneway = true end if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then - way.direction = Way.oneway + way.backward.mode = 0 elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then - way.direction = Way.bidirectional + -- prevent implied oneway elseif onewayClass == "-1" then - way.direction = Way.opposite + way.forward.mode = 0 elseif oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif cycleway and string.find(cycleway, "opposite") == 1 then + -- prevent implied oneway + elseif string.find(cycleway, "opposite") == 1 then if impliedOneway then - way.direction = Way.opposite - else - way.direction = Way.bidirectional + way.forward.mode = 0 + way.backward.mode = mode_normal end - elseif cycleway_left and cycleway_tags[cycleway_left] and cycleway_right and cycleway_tags[cycleway_right] then - way.direction = Way.bidirectional - elseif cycleway_left and cycleway_tags[cycleway_left] then + elseif cycleway_tags[cycleway_left] and cycleway_tags[cycleway_right] then + -- prevent implied + elseif cycleway_tags[cycleway_left] then if impliedOneway then - way.direction = Way.opposite - else - way.direction = Way.bidirectional + way.forward.mode = 0 + way.backward.mode = mode_normal end - elseif cycleway_right and cycleway_tags[cycleway_right] then + elseif cycleway_tags[cycleway_right] then if impliedOneway then - way.direction = Way.oneway - else - way.direction = Way.bidirectional + way.forward.mode = mode_normal + way.backward.mode = 0 end elseif oneway == "-1" then - way.direction = Way.opposite - elseif oneway == "yes" or oneway == "1" or oneway == "true" then - way.direction = Way.oneway - end + way.forward.mode = 0 + elseif oneway == "yes" or oneway == "1" or oneway == "true" or impliedOneway then + way.backward.mode = 0 + end + -- pushing bikes if bicycle_speeds[highway] or pedestrian_speeds[highway] then - if foot ~= 'no' then + if foot ~= "no" then if junction ~= "roundabout" 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 + if way.backward.mode == 0 then + way.backward.speed = walking_speed + way.backward.mode = mode_pushing + elseif way.forward.mode == 0 then + way.forward.speed = walking_speed + way.forward.mode = mode_pushing end 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 = bicycle_speeds["cycleway"] - elseif cycleway_left and cycleway_tags[cycleway_left] then - way.speed = bicycle_speeds["cycleway"] - elseif cycleway_right and cycleway_tags[cycleway_right] then - way.speed = bicycle_speeds["cycleway"] + -- cycleway speed + if cycleway_tags[cycleway_right] then + way.forward.speed = bicycle_speeds["cycleway"] + elseif cycleway_tags[cycleway] then + way.forward.speed = bicycle_speeds["cycleway"] + end + if cycleway_tags[cycleway_left] then + way.backward.speed = bicycle_speeds["cycleway"] + elseif cycleway_tags[cycleway] then + way.backward.speed = bicycle_speeds["cycleway"] end - -- surfaces - if surface then - surface_speed = surface_speeds[surface] - if surface_speed then - way.speed = math.min(way.speed, surface_speed) - way.backward_speed = math.min(way.backward_speed, surface_speed) - end - end - - -- maxspeed - -- 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 + -- dismount + if bicycle == "dismount" then + way.mode = mode_pushing + way.speed = walking_speed 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 + -- surfaces + if surface_speeds[surface] then + way.forward.speed = math.min(way.forward.speed, surface_speeds[surface]) + way.backward.speed = math.min(way.backward.speed, surface_speeds[surface]) end - - - way.type = 1 - return 1 + -- maxspeed + MaxSpeed.limit( way, maxspeed, maxspeed_forward, maxspeed_backward ) + + return true end function turn_function (angle) diff --git a/profiles/car.lua b/profiles/car.lua index 7a6999d3e62..e117c4194ae 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -130,39 +130,46 @@ function way_function (way) 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 ); + way.forward.mode = 2 + way.backward.mode = 2 end - way.direction = Way.bidirectional if speed_profile[route] ~= nil then highway = route; end if tonumber(way.duration) < 0 then - way.speed = speed_profile[highway] + way.forward.speed = speed_profile[highway] + way.backward.speed = speed_profile[highway] end end -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then + if speed_profile[highway] ~= nil then + way.forward.mode = 1 + way.backward.mode = 1 if maxspeed > speed_profile[highway] then - way.speed = maxspeed + way.forward.speed = maxspeed + way.backward.speed = maxspeed else if 0 == maxspeed then maxspeed = math.huge end - way.speed = math.min(speed_profile[highway], maxspeed) + way.forward.speed = math.min(speed_profile[highway], maxspeed) + way.backward.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 "" ~= highway and access_tag_whitelist[access] then if 0 == maxspeed then maxspeed = math.huge end - way.speed = math.min(speed_profile["default"], maxspeed) + way.forward.speed = math.min(speed_profile["default"], maxspeed) + way.backward.speed = math.min(speed_profile["default"], maxspeed) end -- Set access restriction flag if access is allowed under certain restrictions only @@ -178,27 +185,23 @@ function way_function (way) -- 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 + way.forward.mode = 0 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 + way.backward.mode = 0 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 + if way.forward.mode>0 and way.backward.mode>0 then + way.backward.speed = way.forward.speed end - way.speed = maxspeed_forward + way.forward.speed = maxspeed_forward end if maxspeed_backward ~= nil and maxspeed_backward > 0 then - way.backward_speed = maxspeed_backward + way.backward.speed = maxspeed_backward end -- Override general direction settings of there is a specific one for our mode of travel @@ -206,7 +209,6 @@ function way_function (way) if ignore_in_grid[highway] ~= nil and ignore_in_grid[highway] then way.ignore_in_grid = true end - way.type = 1 return 1 end diff --git a/profiles/foot.lua b/profiles/foot.lua index 6a15fb2eab8..c12c751133f 100644 --- a/profiles/foot.lua +++ b/profiles/foot.lua @@ -6,31 +6,31 @@ bollards_whitelist = { [""] = true, ["cattle_grid"] = true, ["border_control"] = access_tag_whitelist = { ["yes"] = true, ["foot"] = true, ["permissive"] = true, ["designated"] = true } access_tag_blacklist = { ["no"] = true, ["private"] = true, ["agricultural"] = true, ["forestery"] = true } access_tag_restricted = { ["destination"] = true, ["delivery"] = true } -access_tags = { "foot" } +access_tags = { "foot", "access" } service_tag_restricted = { ["parking_aisle"] = true } ignore_in_grid = { ["ferry"] = true } restriction_exception_tags = { "foot" } speed_profile = { - ["primary"] = 5, - ["primary_link"] = 5, - ["secondary"] = 5, - ["secondary_link"] = 5, - ["tertiary"] = 5, - ["tertiary_link"] = 5, - ["unclassified"] = 5, - ["residential"] = 5, - ["road"] = 5, - ["living_street"] = 5, - ["service"] = 5, - ["track"] = 5, - ["path"] = 5, - ["steps"] = 5, - ["ferry"] = 5, - ["pedestrian"] = 5, - ["footway"] = 5, - ["pier"] = 5, - ["default"] = 5 + ["primary"] = 5, + ["primary_link"] = 5, + ["secondary"] = 5, + ["secondary_link"] = 5, + ["tertiary"] = 5, + ["tertiary_link"] = 5, + ["unclassified"] = 5, + ["residential"] = 5, + ["road"] = 5, + ["living_street"] = 5, + ["service"] = 5, + ["track"] = 5, + ["path"] = 5, + ["steps"] = 5, + ["ferry"] = 5, + ["pedestrian"] = 5, + ["footway"] = 5, + ["pier"] = 5, + ["default"] = 5 } @@ -45,39 +45,39 @@ use_turn_restrictions = false -- 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 function node_function (node) - local barrier = node.tags:Find ("barrier") - local access = node.tags:Find ("access") - 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 - - if obey_bollards then - --flag node as unpassable if it black listed as unpassable - if access_tag_blacklist[barrier] then - node.bollard = true; - end - - --reverse the previous flag if there is an access tag specifying entrance - if node.bollard and not bollards_whitelist[barrier] and not access_tag_whitelist[barrier] then - node.bollard = false; - end - end - return 1 + local barrier = node.tags:Find ("barrier") + local access = node.tags:Find ("access") + 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 + + if obey_bollards then + --flag node as unpassable if it black listed as unpassable + if access_tag_blacklist[barrier] then + node.bollard = true; + end + + --reverse the previous flag if there is an access tag specifying entrance + if node.bollard and not bollards_whitelist[barrier] and not access_tag_whitelist[barrier] then + node.bollard = false; + end + end + return true end function way_function (way) - -- First, get the properties of each way that we come across + -- 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") @@ -87,107 +87,81 @@ function way_function (way) local man_made = way.tags:Find("man_made") local barrier = way.tags:Find("barrier") local oneway = way.tags:Find("oneway") - local onewayClass = way.tags:Find("oneway:foot") + local onewayClass = way.tags:Find("oneway:foot") local duration = way.tags:Find("duration") local service = way.tags:Find("service") local area = way.tags:Find("area") local access = way.tags:Find("access") - -- Second parse the way according to these properties + -- 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] ~=nil and access_tag_blacklist[access] then - return 0; - end - - -- Check if our vehicle types are forbidden - for i,v in ipairs(access_tags) do - local mode_value = way.tags:Find(v) - if nil ~= mode_value and "no" == mode_value then - return 0; - end + if ignore_areas and "yes"==area then + return false end - - - -- Set the name that will be used for instructions - if "" ~= ref then - way.name = ref - elseif "" ~= name then - way.name = name - end - - if "roundabout" == junction then - way.roundabout = true; - end - - -- Handling ferries and piers - - if (speed_profile[route] ~= nil and speed_profile[route] > 0) or - (speed_profile[man_made] ~= nil and speed_profile[man_made] > 0) - then - if durationIsValid(duration) then - way.speed = parseDuration(duration) / math.max(1, numberOfNodesInWay-1); - way.is_duration_set = true; - end - way.direction = Way.bidirectional; - if speed_profile[route] ~= nil then - highway = route; - elseif speed_profile[man_made] ~= nil then - highway = man_made; - end - if not way.is_duration_set then - way.speed = speed_profile[highway] - end - - end - - -- Set the avg speed on the way if it is accessible by road class - if (speed_profile[highway] ~= nil and way.speed == -1 ) then - way.speed = speed_profile[highway] + + -- Check if we are allowed to access the way + if access_tag_blacklist[access] and access_tag_blacklist[access] then + return false end - - -- Set the avg speed on ways that are marked accessible - if access_tag_whitelist[access] and way.speed == -1 then - if (0 < maxspeed and not take_minimum_of_speeds) or maxspeed == 0 then - maxspeed = math.huge - end - way.speed = math.min(speed_profile["default"], maxspeed) + + -- Check if our vehicle types are forbidden + for i,v in ipairs(access_tags) do + local mode_value = way.tags:Find(v) + if mode_value and "no"==mode_value then + return 0; + end 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 + + -- Set the name that will be used for instructions + if "" ~= ref then + way.name = ref + elseif "" ~= name then + way.name = name 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 + if "roundabout" == junction then + way.roundabout = true; end - - -- Set direction according to tags on way - if obey_oneway then - if onewayClass == "yes" or onewayClass == "1" or onewayClass == "true" then - way.direction = Way.oneway - elseif onewayClass == "no" or onewayClass == "0" or onewayClass == "false" then - way.direction = Way.bidirectional - elseif onewayClass == "-1" then - way.direction = Way.opposite - else - way.direction = Way.bidirectional - end + + -- Handling ferries and piers + if (speed_profile[route] and speed_profile[route]>0) or (speed_profile[man_made] and speed_profile[man_made]>0) then + way.forward.mode = 2 + way.backward.mode = 2 + if durationIsValid(duration) then + way.duration = math.max( 1, parseDuration(duration) ) + else + way.forward.speed = speed_profile[highway] + way.backward.speed = speed_profile[highway] + end else - way.direction = Way.bidirectional + if speed_profile[route] then + highway = route + elseif speed_profile[man_made] then + highway = man_made + end + if speed_profile[highway] then + way.forward.mode = 1 + way.backward.mode = 1 + way.forward.speed = speed_profile[highway] + way.backward.speed = speed_profile[highway] + end + + -- ignore oneway, but respect oneway:foot + if onewayClass=="yes" or onewayClass=="1" or onewayClass=="true" then + way.backward.mode = 0 + elseif onewayClass=="-1" then + way.forward.mode = 0 + end + + -- restricted areas + if access_tag_restricted[access] then + way.is_access_restricted = true + end + if service_tag_restricted[service] then + way.is_access_restricted = true + end 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 + return true end diff --git a/profiles/lib/maxspeed.lua b/profiles/lib/maxspeed.lua new file mode 100644 index 00000000000..4600c0f0d96 --- /dev/null +++ b/profiles/lib/maxspeed.lua @@ -0,0 +1,17 @@ +local math = math + +module "MaxSpeed" + +function limit(way,max,maxf,maxb) + if maxf and maxf>0 then + way.forward.speed = math.min(way.forward.speed, maxf) + elseif max and max>0 then + way.forward.speed = math.min(way.forward.speed, max) + end + + if maxb and maxb>0 then + way.backward.speed = math.min(way.backward.speed, maxb) + elseif max and max>0 then + way.backward.speed = math.min(way.backward.speed, max) + end +end diff --git a/profiles/testbot.lua b/profiles/testbot.lua index f934fead5d9..cee1f9f842e 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -6,10 +6,19 @@ -- Secondary road: 18km/h = 18000m/3600s = 100m/20s -- Tertiary road: 12km/h = 12000m/3600s = 100m/30s +-- modes: +-- 1: normal +-- 2: route +-- 3: river downstream +-- 4: river upstream +-- 5: steps down +-- 6: steps up + speed_profile = { ["primary"] = 36, ["secondary"] = 18, ["tertiary"] = 12, + ["steps"] = 6, ["default"] = 24 } @@ -23,6 +32,14 @@ ignore_areas = true -- future feature traffic_signal_penalty = 7 -- seconds u_turn_penalty = 20 +modes = { "bot", "ferry", "downstream", "upstream" } + +function get_modes(vector) + for i,v in ipairs(modes) do + vector:Add(v) + end +end + function limit_speed(speed, limits) -- don't use ipairs(), since it stops at the first nil value for i=1, #limits do @@ -60,48 +77,50 @@ function way_function (way) if route ~= nil and durationIsValid(duration) then way.duration = math.max( 1, parseDuration(duration) ) + way.forward.mode = 2 + way.backward.mode = 2 else - local speed_forw = speed_profile[highway] or speed_profile['default'] - local speed_back = speed_forw + local speed = speed_profile[highway] or speed_profile['default'] if highway == "river" then - local temp_speed = speed_forw; - speed_forw = temp_speed*1.5 - speed_back = temp_speed/1.5 - end + way.forward.mode = 3 + way.backward.mode = 4 + way.forward.speed = speed*1.5 + way.backward.speed = speed/1.5 + else + if highway == "steps" then + way.forward.mode = 5 + way.backward.mode = 6 + else + way.forward.mode = 1 + way.backward.mode = 1 + end + way.forward.speed = speed + way.backward.speed = speed + end if maxspeed_forward ~= nil and maxspeed_forward > 0 then - speed_forw = maxspeed_forward + way.forward.speed = maxspeed_forward else - if maxspeed ~= nil and maxspeed > 0 and speed_forw > maxspeed then - speed_forw = maxspeed + if maxspeed ~= nil and maxspeed > 0 and way.forward.speed > maxspeed then + way.forward.speed = maxspeed end end if maxspeed_backward ~= nil and maxspeed_backward > 0 then - speed_back = maxspeed_backward + way.backward.speed = maxspeed_backward else - if maxspeed ~=nil and maxspeed > 0 and speed_back > maxspeed then - speed_back = maxspeed + if maxspeed ~=nil and maxspeed > 0 and way.backward.speed > maxspeed then + way.backward.speed = maxspeed end - end - - way.speed = speed_forw - if speed_back ~= way_forw then - way.backward_speed = speed_back - end + end end - if oneway == "no" or oneway == "0" or oneway == "false" then - way.direction = Way.bidirectional - elseif oneway == "-1" then - way.direction = Way.opposite + if oneway == "-1" then + way.forward.mode = 0 elseif oneway == "yes" or oneway == "1" or oneway == "true" then - way.direction = Way.oneway - else - way.direction = Way.bidirectional + way.backward.mode = 0 end - way.type = 1 return 1 end