diff --git a/CMakeLists.txt b/CMakeLists.txt index 9881da81f..d8f557c3a 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 e42dad3a7..3aaba4933 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 @@ public: 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 fce247d31..9af857159 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -74,6 +74,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vectorisAccessRestricted(); 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 +148,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( currentNode.id = data.edgeBasedNodeID; currentNode.ignoreInGrid = data.ignoreInGrid; currentNode.weight = data.distance; + currentNode.mode = data.mode; edgeBasedNodes.push_back(currentNode); } @@ -274,7 +276,9 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State distance += speedProfile.trafficSignalPenalty; } unsigned penalty = 0; - TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, penalty, myLuaState); + bool contraflow; + + TurnInstruction turnInstruction = AnalyzeTurn(u, v, w, contraflow, penalty, myLuaState); if(turnInstruction == TurnInstructions.UTurn) distance += speedProfile.uTurnPenalty; // if(!edgeData1.isAccessRestricted && edgeData2.isAccessRestricted) { @@ -283,11 +287,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; @@ -326,7 +329,7 @@ void EdgeBasedGraphFactory::Run(const char * originalEdgeDataFilename, lua_State INFO("Generated " << edgeBasedNodes.size() << " edge based nodes"); } -TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const { +TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, bool& contraflow, unsigned& penalty, lua_State *myLuaState) const { const double angle = GetAngleBetweenTwoEdges(inputNodeInfoList[u], inputNodeInfoList[v], inputNodeInfoList[w]); if( speedProfile.has_turn_penalty_function ) { @@ -351,12 +354,7 @@ 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; - } + contraflow = data2.contraFlow; //roundabouts need to be handled explicitely if(data1.roundabout && data2.roundabout) { @@ -379,8 +377,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 e751a7169..04caaf734 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -77,6 +77,7 @@ public: NodeID nameID; unsigned weight:31; bool ignoreInGrid:1; + TravelMode mode; }; struct SpeedProfileProperties{ @@ -99,6 +100,7 @@ private: bool roundabout:1; bool ignoreInGrid:1; bool contraFlow:1; + TravelMode mode; }; struct _EdgeBasedEdgeData { @@ -108,6 +110,7 @@ private: bool forward; bool backward; TurnInstruction turnInstruction; + TravelMode mode; }; typedef DynamicGraph< _NodeBasedEdgeData > _NodeBasedDynamicGraph; @@ -147,7 +150,7 @@ public: void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); void GetEdgeBasedNodes( DeallocatingVector< EdgeBasedNode> & nodes); void GetOriginalEdgeData( std::vector< OriginalEdgeData> & originalEdgeData); - TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, unsigned& penalty, lua_State *myLuaState) const; + TurnInstruction AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w, bool& contraflow, unsigned& penalty, lua_State *myLuaState) const; unsigned GetNumberOfNodes() const; }; diff --git a/DataStructures/GridEdge.h b/DataStructures/GridEdge.h index 7b2dd7825..a7f633374 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 714560ccc..823de0744 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,8 +42,8 @@ public: 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, short ty, bool ra, bool ig, bool ar, bool cf, TravelMode mode) : + _source(s), _target(t), _name(n), _weight(w), forward(f), backward(b), _type(ty), _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), _contraFlow(cf), _mode(mode) { if(ty < 0) {ERR("Type: " << ty);}; } NodeID target() const {return _target; } NodeID source() const {return _source; } @@ -56,6 +58,7 @@ public: bool ignoreInGrid() const { return _ignoreInGrid; } bool isAccessRestricted() const { return _accessRestricted; } bool isContraFlow() const { return _contraFlow; } + TravelMode mode() const { return _mode; } NodeID _source; NodeID _target; @@ -68,11 +71,12 @@ public: 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), _type(0), _roundabout(false), _ignoreInGrid(false), _accessRestricted(false), _contraFlow(false), _mode(0) { assert(false); } //shall not be used. }; @@ -127,7 +131,7 @@ public: 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 000000000..2bb64fc0d --- /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 22cb4e2d4..51ea4e108 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 @@ public: 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 @@ public: 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 @@ public: } -private: +protected: inline unsigned GetCellIndexFromRAMAndFileIndex(const unsigned ramIndex, const unsigned fileIndex) const { unsigned lineBase = ramIndex/1024; lineBase = lineBase*32*32768; @@ -589,14 +500,30 @@ private: 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 029d30def..ac9208587 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ private: 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 2827d7a91..57dcba637 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 3a2aecb82..8a9c7a20c 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 cbe4b81cc..ff4ca117f 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 000000000..a38e1b6cb --- /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 46a1d5b82..aed2dd41a 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 72a011b55..dd0d1142f 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -312,7 +312,7 @@ public: 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 @@ public: 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 6981e9570..b7b42cb10 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 6a19efa07..8ed7bf228 100644 --- a/Extractor/BaseParser.h +++ b/Extractor/BaseParser.h @@ -46,6 +46,7 @@ public: 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 @@ protected: 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 b2476bc86..328525cd0 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -257,6 +257,7 @@ void ExtractionContainers::PrepareData(const std::string & outputFileName, const 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 +266,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 c8b5fc1aa..dcfa2cdbb 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -69,7 +69,7 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { 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); @@ -108,7 +108,8 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { parsed_way.roundabout, parsed_way.ignoreInGrid, (0 < parsed_way.duration), - parsed_way.isAccessRestricted + parsed_way.isAccessRestricted, + parsed_way.forward_mode ) ); externalMemory->usedNodeIDs.push_back(parsed_way.path[n]); @@ -132,7 +133,8 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { parsed_way.ignoreInGrid, (0 < parsed_way.duration), parsed_way.isAccessRestricted, - (ExtractionWay::oneway == parsed_way.direction) + (ExtractionWay::oneway == parsed_way.direction), + parsed_way.backward_mode ) ); } diff --git a/Extractor/ExtractorStructs.h b/Extractor/ExtractorStructs.h index fe21da957..eada00662 100644 --- a/Extractor/ExtractorStructs.h +++ b/Extractor/ExtractorStructs.h @@ -35,6 +35,7 @@ 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; @@ -59,8 +60,10 @@ struct ExtractionWay { roundabout = false; isAccessRestricted = false; ignoreInGrid = false; + forward_mode = 0; + backward_mode = 0; } - + enum Directions { notSure = 0, oneway, bidirectional, opposite }; @@ -76,6 +79,8 @@ struct ExtractionWay { bool roundabout; bool isAccessRestricted; bool ignoreInGrid; + TravelMode forward_mode; + TravelMode backward_mode; std::vector< NodeID > path; HashTable keyVals; }; @@ -89,13 +94,13 @@ 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() : start(0), target(0), type(0), direction(0), speed(0), nameID(0), isRoundabout(false), ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), isContraFlow(false), mode(0) {}; 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) { + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, TravelMode _mode): start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false), mode(_mode) { 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) { + InternalExtractorEdge(NodeID s, NodeID t, short tp, short d, double sp, unsigned nid, bool isra, bool iing, bool ids, bool iar, bool icf, TravelMode _mode) : start(s), target(t), type(tp), direction(d), speed(sp), nameID(nid), isRoundabout(isra), ignoreInGrid(iing), isDurationSet(ids), isAccessRestricted(iar), isContraFlow(false), mode(_mode) { assert(0 <= type); } NodeID start; @@ -109,7 +114,8 @@ struct InternalExtractorEdge { bool isDurationSet; bool isAccessRestricted; bool isContraFlow; - + TravelMode mode; + _Coordinate startCoord; _Coordinate targetCoord; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index 6405802f8..4f28ed4f4 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -319,7 +319,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 6bab21c5f..1a9cd6178 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -78,6 +78,8 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { .def_readwrite("ignore_in_grid", &ExtractionWay::ignoreInGrid) .def_readwrite("tags", &ExtractionWay::keyVals) .def_readwrite("direction", &ExtractionWay::direction) + .def_readwrite("forward_mode", &ExtractionWay::forward_mode) + .def_readwrite("backward_mode", &ExtractionWay::backward_mode) .enum_("constants") [ luabind::value("notSure", 0), diff --git a/Plugins/RawRouteData.h b/Plugins/RawRouteData.h index f0c105486..0a7fde780 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/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index f329c697b..5a73ec26e 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -101,7 +101,7 @@ public: } } - 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 @@ public: 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 @@ public: 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 66d374079..f893c80db 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -69,7 +69,7 @@ public: 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 @@ public: 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 @@ public: 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 325cdb97d..6a5e17e84 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 be8bba073..28f82c270 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 66401548c..4b3454c82 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -102,7 +102,8 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL NodeID nameID; int length; bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow; - + TravelMode mode; + for (EdgeID i=0; i& edgeL in.read((char*)&ignoreInGrid, sizeof(bool)); in.read((char*)&isAccessRestricted, sizeof(bool)); in.read((char*)&isContraFlow, sizeof(bool)); + in.read((char*)&mode, sizeof(TravelMode)); GUARANTEE(length > 0, "loaded null length edge" ); GUARANTEE(weight > 0, "loaded null weight"); @@ -151,7 +153,7 @@ NodeID readBinaryOSRMGraphFromStream(std::istream &in, std::vector& edgeL std::swap(forward, backward); } - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow ); + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, mode ); edgeList.push_back(inputEdge); } std::sort(edgeList.begin(), edgeList.end()); @@ -367,7 +369,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 7156cef32..d994caad8 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/mode.feature b/features/bicycle/mode.feature index c24af4686..cf9afeeee 100644 --- a/features/bicycle/mode.feature +++ b/features/bicycle/mode.feature @@ -1,10 +1,14 @@ @routing @bicycle @mode Feature: Bike - Mode flag +# bicycle modes: +# 1 bike +# 2 ferry +# 3 push + Background: Given the profile "bicycle" - @todo Scenario: Bike - Mode when using a ferry Given the node map | a | b | | @@ -17,15 +21,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,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 | + | 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 | - @todo Scenario: Bike - Mode when pushing bike against oneways Given the node map | a | b | | @@ -38,15 +41,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 | + | 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,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,1 | + | b | d | bc,cd | head,left,destination | 1,1 | - @todo Scenario: Bike - Mode when pushing on pedestrain streets Given the node map | a | b | | @@ -59,15 +61,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 | + | 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 | - @todo Scenario: Bike - Mode when pushing on pedestrain areas Given the node map | a | b | | | @@ -80,10 +81,10 @@ 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,3,1 | + | f | a | df,bcd,ab | 1,3,1 | + | d | a | bcd,ab | 3,1 | + | f | b | df,bcd | 1,3 | + | a | d | ab,bcd | 1,3 | + | b | f | bcd,df | 3,1 | diff --git a/features/bicycle/pushing.feature b/features/bicycle/pushing.feature index 13590d07b..951f78150 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/testbot/mode.feature b/features/testbot/mode.feature index 3192c48f9..4d6132b2e 100644 --- a/features/testbot/mode.feature +++ b/features/testbot/mode.feature @@ -1,26 +1,82 @@ @routing @testbot @mode Feature: Testbot - Mode flag +# testbot modes: +# 1 normal +# 2 route +# 3 river downstream +# 4 river upstream + Background: Given the profile "testbot" - @todo - Scenario: Bike - Mode - Given the node map - | a | b | | - | | c | d | + 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 | | | + 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 | 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 | + 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 | + + 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 | diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 98d03c83d..609e5ae91 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -177,6 +177,8 @@ 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") -- name if "" ~= ref and "" ~= name then @@ -189,7 +191,10 @@ function way_function (way) way.name = "{highway:"..highway.."}" -- if no name exists, use way type -- this encoding scheme is excepted to be a temporary solution end - + + way.forward_mode = 1 + way.backward_mode = 1 + -- speed if route_speeds[route] then -- ferries (doesn't cover routes tagged using relations) @@ -200,6 +205,8 @@ function way_function (way) else way.speed = route_speeds[route] end + way.forward_mode = 2 + way.backward_mode = 2 elseif railway and platform_speeds[railway] then -- railway platforms (old tagging scheme) way.speed = platform_speeds[railway] @@ -224,16 +231,30 @@ function way_function (way) 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.forward_mode = 3 + way.backward_mode = 3 elseif man_made and man_made_speeds[man_made] then -- man made structures way.speed = man_made_speeds[man_made] + way.forward_mode = 3 + way.backward_mode = 3 elseif foot == 'yes' then way.speed = walking_speed + way.forward_mode = 3 + way.backward_mode = 3 + elseif foot_forward == 'yes' then + way.speed = walking_speed + way.forward_mode = 3 + way.backward_mode = 0 + elseif foot_backward == 'yes' then + way.speed = 0 + way.backward_speed = walking_speed + way.forward_mode = 0 + way.backward_mode = 3 end end end @@ -286,14 +307,15 @@ function way_function (way) if junction ~= "roundabout" then if way.direction == Way.oneway then way.backward_speed = walking_speed + way.backward_mode = 3 elseif way.direction == Way.opposite then way.backward_speed = walking_speed + way.backward_mode = 3 way.speed = way.speed 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 @@ -336,8 +358,6 @@ function way_function (way) way.backward_speed = maxspeed_backward end - - way.type = 1 return 1 end diff --git a/profiles/testbot.lua b/profiles/testbot.lua index f934fead5..d3fd6d4ea 100644 --- a/profiles/testbot.lua +++ b/profiles/testbot.lua @@ -6,6 +6,12 @@ -- 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 + speed_profile = { ["primary"] = 36, ["secondary"] = 18, @@ -23,6 +29,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 @@ -56,10 +70,14 @@ function way_function (way) local maxspeed_forward = tonumber(way.tags:Find( "maxspeed:forward")) local maxspeed_backward = tonumber(way.tags:Find( "maxspeed:backward")) + way.forward_mode = 1 + way.backward_mode = 1 way.name = name 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 @@ -68,7 +86,9 @@ function way_function (way) 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 + end if maxspeed_forward ~= nil and maxspeed_forward > 0 then speed_forw = maxspeed_forward