From 9a6cf7b991542e0079103fbad42bb7178b2706e2 Mon Sep 17 00:00:00 2001 From: DennisOSRM Date: Wed, 16 Nov 2011 17:29:00 +0100 Subject: [PATCH] Add first nodes with negative weights --- Contractor/EdgeBasedGraphFactory.cpp | 23 +++-- Contractor/EdgeBasedGraphFactory.h | 5 +- DataStructures/ExtractorStructs.h | 4 +- DataStructures/GridEdge.h | 6 +- DataStructures/NNGrid.h | 50 +++++++++-- DataStructures/PhantomNodes.h | 11 ++- DataStructures/PolylineCompressor.h | 2 + DataStructures/SearchEngine.h | 104 ++++++++-------------- Plugins/BaseDescriptor.h | 124 +-------------------------- Plugins/JSONDescriptor.h | 85 +++++------------- Plugins/ViaRoutePlugin.h | 83 +++++++++++------- 11 files changed, 182 insertions(+), 315 deletions(-) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 9ceda66a5..f613990fc 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -130,12 +130,12 @@ void EdgeBasedGraphFactory::Run() { if( !isTurnProhibited ) { //only add an edge if turn is not prohibited //new costs for edge based edge (e1, e2) = cost (e1) + tc(e1,e2) const _NodeBasedDynamicGraph::NodeIterator edgeBasedSource = _nodeBasedGraph->GetEdgeData(e1).edgeBasedNodeID; -// INFO("edgeBasedSource: " << edgeBasedSource); + // INFO("edgeBasedSource: " << edgeBasedSource); if(edgeBasedSource > _nodeBasedGraph->GetNumberOfEdges()) { ERR("edgeBasedTarget" << edgeBasedSource << ">" << _nodeBasedGraph->GetNumberOfEdges()); } const _NodeBasedDynamicGraph::NodeIterator edgeBasedTarget = _nodeBasedGraph->GetEdgeData(e2).edgeBasedNodeID; -// INFO("edgeBasedTarget: " << edgeBasedTarget); + // INFO("edgeBasedTarget: " << edgeBasedTarget); if(edgeBasedTarget > _nodeBasedGraph->GetNumberOfEdges()) { ERR("edgeBasedTarget" << edgeBasedTarget << ">" << _nodeBasedGraph->GetNumberOfEdges()); } @@ -150,9 +150,14 @@ void EdgeBasedGraphFactory::Run() { newEdge.data.via = v; newEdge.data.nameID1 = _nodeBasedGraph->GetEdgeData(e1).middleName.nameID; newEdge.data.nameID2 = _nodeBasedGraph->GetEdgeData(e2).middleName.nameID; - //Todo: turn type angeben - newEdge.data.turnInstruction = 0; + //Todo: turn instruction angeben + if(newEdge.data.nameID1 == newEdge.data.nameID2) + newEdge.data.turnInstruction = 0; + else { + //TODO: Winkel berechnen und angepasste Anweisung geben. + newEdge.data.turnInstruction = 1; + } //create Edge for NearestNeighborlookup edgeBasedEdges.push_back(newEdge); EdgeBasedNode currentNode; @@ -164,15 +169,7 @@ void EdgeBasedGraphFactory::Run() { currentNode.lat2 = inputNodeInfoList[v].lat; currentNode.lon2 = inputNodeInfoList[v].lon; currentNode.id = edgeBasedSource; - edgeBasedNodes.push_back(currentNode); - } - if(_nodeBasedGraph->GetEdgeData(e2).type != 14) { - currentNode.nameID = newEdge.data.nameID2; - currentNode.lat1 = inputNodeInfoList[v].lat; - currentNode.lon1 = inputNodeInfoList[v].lon; - currentNode.lat2 = inputNodeInfoList[w].lat; - currentNode.lon2 = inputNodeInfoList[w].lon; - currentNode.id = edgeBasedTarget; + currentNode.weight = _nodeBasedGraph->GetEdgeData(e1).distance; edgeBasedNodes.push_back(currentNode); } } else { diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index c8eb95b0f..8b6035522 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -42,7 +42,7 @@ private: }; struct _NodeBasedEdgeData { - unsigned distance; + int distance; unsigned edgeBasedNodeID; unsigned originalEdges; bool shortcut; @@ -53,7 +53,7 @@ private: } data; struct _EdgeBasedEdgeData { - unsigned distance; + int distance; unsigned via; unsigned nameID1; unsigned nameID2; @@ -79,6 +79,7 @@ public: int lon2; NodeID id; NodeID nameID; + unsigned weight; }; typedef DynamicGraph< _EdgeBasedEdgeData> _EdgeBasedDynamicGraph; diff --git a/DataStructures/ExtractorStructs.h b/DataStructures/ExtractorStructs.h index 69950506c..84fab1d30 100644 --- a/DataStructures/ExtractorStructs.h +++ b/DataStructures/ExtractorStructs.h @@ -27,11 +27,11 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "Util.h" struct _PathData { - _PathData(NodeID no, unsigned na, unsigned tu, unsigned le) : node(no), nameID(na), turnInstruction(tu), lengthOfSegment(le) { } + _PathData(NodeID no, unsigned na, unsigned tu, unsigned le) : node(no), nameID(na), lengthOfSegment(le), turnInstruction(tu) { } NodeID node; unsigned nameID; - unsigned turnInstruction; unsigned lengthOfSegment; + short turnInstruction; }; typedef boost::unordered_map StringMap; diff --git a/DataStructures/GridEdge.h b/DataStructures/GridEdge.h index 4398c9bcc..e1865f6a7 100644 --- a/DataStructures/GridEdge.h +++ b/DataStructures/GridEdge.h @@ -22,9 +22,11 @@ or see http://www.gnu.org/licenses/agpl.txt. #define GRIDEDGE_H_ struct _GridEdge { - _GridEdge(NodeID n, _Coordinate sc, _Coordinate tc) : edgeBasedNode(n), startCoord(sc), targetCoord(tc) {} - _GridEdge() : edgeBasedNode(UINT_MAX) {} + _GridEdge(NodeID n, NodeID na, int w, _Coordinate sc, _Coordinate tc) : edgeBasedNode(n), nameID(na), weight(w), startCoord(sc), targetCoord(tc) {} + _GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX) {} NodeID edgeBasedNode; + NodeID nameID; + int weight; _Coordinate startCoord; _Coordinate targetCoord; }; diff --git a/DataStructures/NNGrid.h b/DataStructures/NNGrid.h index 50824b7fb..0922d88fb 100644 --- a/DataStructures/NNGrid.h +++ b/DataStructures/NNGrid.h @@ -198,7 +198,7 @@ public: int tlat = 100000*lat2y(edge.lat2/100000.); int tlon = edge.lon2; AddEdge( _GridEdge( - edge.id, edge.nameID, + edge.id, edge.nameID, edge.weight, _Coordinate(slat, slon), _Coordinate(tlat, tlon) ) ); @@ -300,26 +300,55 @@ public: } } - _Coordinate tmp; + _GridEdge smallestEdge; + _Coordinate tmp, newEndpoint; double dist = (numeric_limits::max)(); BOOST_FOREACH(_GridEdge candidate, candidates) { double r = 0.; double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r); - if((tmpDist == dist) && 1 == std::abs((int)candidate.edgeBasedNode-(int)resultNode.edgeBasedNode)) { + if(DoubleEpsilonCompare(dist, tmpDist) && 1 == std::abs((int)candidate.edgeBasedNode-(int)resultNode.edgeBasedNode)) { resultNode.isBidirected = true; - resultNode.edgeBasedNode = std::min(candidate.edgeBasedNode, resultNode.edgeBasedNode); + resultNode.weight2 = candidate.weight; + /* if(resultNode.weight1 != resultNode.weight2) { + ERR("w1: " << resultNode.weight1 << ", w2: " << resultNode.weight2); + assert(false); + }*/ + if(candidate.edgeBasedNode < resultNode.edgeBasedNode) { + resultNode.edgeBasedNode = candidate.edgeBasedNode; + std::swap(resultNode.weight1, resultNode.weight2); + } } if(tmpDist < dist) { - resultNode.isBidirected = false; + resultNode.Reset(); resultNode.edgeBasedNode = candidate.edgeBasedNode; resultNode.nodeBasedEdgeNameID = candidate.nameID; - resultNode.ratio = r; + resultNode.weight1 = candidate.weight; dist = tmpDist; resultNode.location.lat = round(100000*(y2lat(static_cast(tmp.lat)/100000.))); resultNode.location.lon = tmp.lon; foundNode = true; + smallestEdge = candidate; + newEndpoint = tmp; } } + +// INFO("startcoord: " << smallestEdge.startCoord << ", tgtcoord" << smallestEdge.targetCoord << "result: " << newEndpoint); +// INFO("length of old edge: " << LengthOfVector(smallestEdge.startCoord, smallestEdge.targetCoord)); +// INFO("Length of new edge: " << LengthOfVector(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")); +// } + + double ratio = std::min(1., LengthOfVector(smallestEdge.startCoord, newEndpoint)/LengthOfVector(smallestEdge.startCoord, smallestEdge.targetCoord) ); + assert(ratio >= 0 && ratio <=1); +// INFO("Old weight1: " << resultNode.weight1 << ", old weight2: " << resultNode.weight2); + resultNode.weight1 *= ratio; + if(resultNode.isBidirected) { + resultNode.weight2 *= (1-ratio); +// INFO("New weight1: " << resultNode.weight1 << ", new weight2: " << resultNode.weight2); + } return foundNode; } @@ -375,6 +404,15 @@ public: private: + inline double LengthOfVector(const _Coordinate & c1, const _Coordinate & c2) { + double length1 = std::sqrt(c1.lat/100000.*c1.lat/100000. + c1.lon/100000.*c1.lon/100000.); + double length2 = std::sqrt(c2.lat/100000.*c2.lat/100000. + c2.lon/100000.*c2.lon/100000.); + return std::fabs(length1-length2); + } + + inline bool DoubleEpsilonCompare(const double d1, const double d2) { + return (std::fabs(d1 - d2) < 0.000000001); + } unsigned FillCell(std::vector& entriesWithSameRAMIndex, unsigned fileOffset ) { vector * tmpBuffer = new vector(); diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h index 5e1a656e8..a7265026f 100644 --- a/DataStructures/PhantomNodes.h +++ b/DataStructures/PhantomNodes.h @@ -24,18 +24,21 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "ExtractorStructs.h" struct PhantomNode { - PhantomNode() : isBidirected(false), edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), ratio(1.) {} + PhantomNode() : isBidirected(false), edgeBasedNode(UINT_MAX), nodeBasedEdgeNameID(UINT_MAX), weight1(INT_MAX), weight2(INT_MAX) {} bool isBidirected; NodeID edgeBasedNode; unsigned nodeBasedEdgeNameID; - double ratio; + int weight1; + int weight2; _Coordinate location; void Reset() { + isBidirected = false; edgeBasedNode = UINT_MAX; - ratio = 1.; + nodeBasedEdgeNameID = UINT_MAX; + weight1 = INT_MAX; + weight2 = INT_MAX; location.Reset(); } - }; struct PhantomNodes { diff --git a/DataStructures/PolylineCompressor.h b/DataStructures/PolylineCompressor.h index c5ae91e91..f89f10f63 100644 --- a/DataStructures/PolylineCompressor.h +++ b/DataStructures/PolylineCompressor.h @@ -25,6 +25,8 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "ExtractorStructs.h" +#include "../Util/StringUtil.h" + class PolylineCompressor { private: inline void encodeVectorSignedNumber(vector & numbers, string & output) { diff --git a/DataStructures/SearchEngine.h b/DataStructures/SearchEngine.h index 3e6bfb347..22d368965 100644 --- a/DataStructures/SearchEngine.h +++ b/DataStructures/SearchEngine.h @@ -76,10 +76,6 @@ public: result.lon = nodeHelpDesk->getLongitudeOfNode(id); } - unsigned int numberOfNodes() const { - return nodeHelpDesk->getNumberOfNodes(); - } - inline void InitializeThreadLocalStorageIfNecessary() { if(!_forwardHeap.get()) _forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes())); @@ -92,8 +88,8 @@ public: _backwardHeap->Clear(); } - unsigned int ComputeRoute(PhantomNodes & phantomNodes, vector<_PathData> & path) { - unsigned int _upperbound = UINT_MAX; + int ComputeRoute(PhantomNodes & phantomNodes, vector<_PathData> & path) { + int _upperbound = INT_MAX; if(!phantomNodes.AtLeastOnePhantomNodeIsUINTMAX()) return _upperbound; @@ -105,19 +101,19 @@ public: return _upperbound; } //insert start and/or target node of start edge - _forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, 0, phantomNodes.startPhantom.edgeBasedNode); -// INFO("Inserting start1: " << phantomNodes.startPhantom.edgeBasedNode); + _forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, -phantomNodes.startPhantom.weight1, phantomNodes.startPhantom.edgeBasedNode); +// INFO("[FORW] Inserting node " << phantomNodes.startPhantom.edgeBasedNode << " at distance " << -phantomNodes.startPhantom.weight1); if(phantomNodes.startPhantom.isBidirected) { - _forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode+1, 0, phantomNodes.startPhantom.edgeBasedNode+1); -// INFO("Inserting start2: " << phantomNodes.startPhantom.edgeBasedNode+1); + _forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode+1, -phantomNodes.startPhantom.weight2, phantomNodes.startPhantom.edgeBasedNode+1); +// INFO("[FORW] Inserting node " << phantomNodes.startPhantom.edgeBasedNode+1 << " at distance " << -phantomNodes.startPhantom.weight2); } //insert start and/or target node of target edge id - _backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode, 0, phantomNodes.targetPhantom.edgeBasedNode); -// INFO("Inserting target1: " << phantomNodes.targetPhantom.edgeBasedNode); + _backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode, -phantomNodes.targetPhantom.weight1, phantomNodes.targetPhantom.edgeBasedNode); +// INFO("[BACK] Inserting node " << phantomNodes.targetPhantom.edgeBasedNode << " at distance " << -phantomNodes.targetPhantom.weight1); if(phantomNodes.targetPhantom.isBidirected) { - _backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode+1, 0, phantomNodes.targetPhantom.edgeBasedNode+1); -// INFO("Inserting target2: " << phantomNodes.targetPhantom.edgeBasedNode+1); + _backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode+1, -phantomNodes.targetPhantom.weight2, phantomNodes.targetPhantom.edgeBasedNode+1); +// INFO("[BACK] Inserting node " << phantomNodes.targetPhantom.edgeBasedNode+1 << " at distance " << -phantomNodes.targetPhantom.weight2); } while(_forwardHeap->Size() + _backwardHeap->Size() > 0){ @@ -130,7 +126,7 @@ public: } // INFO("bidirectional search iteration ended: " << _forwardHeap->Size() << "," << _backwardHeap->Size() << ", dist: " << _upperbound); - if ( _upperbound == UINT_MAX ) { + if ( _upperbound == INT_MAX ) { return _upperbound; } NodeID pathNode = middle; @@ -156,7 +152,7 @@ public: unsigned int ComputeDistanceBetweenNodes(NodeID start, NodeID target) { InitializeThreadLocalStorageIfNecessary(); NodeID middle(UINT_MAX); - unsigned int _upperbound = UINT_MAX; + int _upperbound = INT_MAX; _forwardHeap->Insert(start, 0, start); _backwardHeap->Insert(target, 0, target); while(_forwardHeap->Size() + _backwardHeap->Size() > 0){ @@ -167,14 +163,13 @@ public: _RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound); } } - return _upperbound; } unsigned int ComputeDistanceBetweenNodesWithStats(NodeID start, NodeID target, _Statistics & stats) { InitializeThreadLocalStorageIfNecessary(); NodeID middle(UINT_MAX); - unsigned int _upperbound = UINT_MAX; + int _upperbound = INT_MAX; _forwardHeap->Insert(start, 0, start); _backwardHeap->Insert(target, 0, target); stats.insertedNodes += 2; @@ -190,11 +185,6 @@ public: return _upperbound; } - inline unsigned int findNearestNodeForLatLon(const _Coordinate & coord, _Coordinate & result) const { - nodeHelpDesk->FindNearestNodeCoordForLatLon(coord, result); - return 0; - } - inline bool FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) { nodeHelpDesk->FindRoutingStarts(start, target, routingStarts); return true; @@ -205,7 +195,6 @@ public: } inline NodeID GetNameIDForOriginDestinationNodeID(NodeID s, NodeID t) const { - //INFO("Getting nameID for s=" << s << " and t=" << t); if(s == t) return 0; @@ -213,7 +202,6 @@ public: if(e == UINT_MAX) e = _graph->FindEdge( t, s ); if(UINT_MAX == e) { - // INFO("edge not found for start " << s << ", target " << t) return 0; } assert(e != UINT_MAX); @@ -221,45 +209,22 @@ public: return ed.via; } - inline NodeID GetWeightForOriginDestinationNodeID(NodeID s, NodeID t) const { - assert(s!=t); - EdgeID e = _graph->FindEdge(s, t); - if(e == UINT_MAX) - e = _graph->FindEdge( t, s ); - assert(e != UINT_MAX); - const EdgeData ed = _graph->GetEdgeData(e); - return ed.distance; - } - - inline std::string & GetUnescapedNameForNameID(const NodeID nameID) const { - return (nameID >= _names->size() ? _names->at(0) : _names->at(nameID)); - } - - inline std::string GetEscapedNameForOriginDestinationNodeID(NodeID s, NodeID t) const { - NodeID nameID = GetNameIDForOriginDestinationNodeID(s, t); - return (GetEscapedNameForNameID(nameID)); - } - inline std::string GetEscapedNameForNameID(const NodeID nameID) const { return ((nameID >= _names->size() || nameID == 0) ? std::string("") : HTMLEntitize(_names->at(nameID))); } - inline short GetTypeOfEdgeForOriginDestinationNodeID(NodeID s, NodeID t) const { - assert(s!=t); - EdgeID e = _graph->FindEdge(s, t); - if(e == UINT_MAX) - e = _graph->FindEdge( t, s ); - assert(e != UINT_MAX); - const EdgeData ed = _graph->GetEdgeData(e); - return ed.type; - } + inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) const { + const unsigned nameID = _graph->GetEdgeData(edgeID).nameID1; + return GetEscapedNameForNameID(nameID); + } private: - inline void _RoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, unsigned int *_upperbound) { + inline void _RoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, int *_upperbound) { const NodeID node = _forwardHeap->DeleteMin(); - const unsigned int distance = _forwardHeap->GetKey(node); + const int distance = _forwardHeap->GetKey(node); +// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " settling " << node << " with distance " << distance); if(_backwardHeap->WasInserted(node)){ - const unsigned int newDistance = _backwardHeap->GetKey(node) + distance; + const int newDistance = _backwardHeap->GetKey(node) + distance; if(newDistance < *_upperbound){ *middle = node; *_upperbound = newDistance; @@ -270,9 +235,9 @@ private: _forwardHeap->DeleteAll(); return; } -/* for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) { + for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) { const NodeID to = _graph->GetTarget(edge); - const EdgeWeight edgeWeight = _graph->GetEdgeData(edge).distance; + const int edgeWeight = _graph->GetEdgeData(edge).distance; assert( edgeWeight > 0 ); @@ -286,19 +251,20 @@ private: } } } -*/ + for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) { const NodeID to = _graph->GetTarget(edge); - const EdgeWeight edgeWeight = _graph->GetEdgeData(edge).distance; + const int edgeWeight = _graph->GetEdgeData(edge).distance; assert( edgeWeight > 0 ); - const int toDistance = distance + edgeWeight; - assert(toDistance > 0); - bool forwardDirectionFlag = (forwardDirection ? _graph->GetEdgeData(edge).forward : _graph->GetEdgeData(edge).backward ); if(forwardDirectionFlag) { + const int toDistance = distance + edgeWeight; +// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " relaxing edge (" << node << "," << to << ") with distance " << toDistance << "=" << distance << "+" << edgeWeight); + //New Node discovered -> Add to Heap + Node Info Storage if ( !_forwardHeap->WasInserted( to ) ) { +// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " inserting node " << to << " at distance " << toDistance); _forwardHeap->Insert( to, toDistance, node ); } //Found a shorter Path -> Update distance @@ -311,7 +277,7 @@ private: } } - inline void _RoutingStepWithStats(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, unsigned int *_upperbound, _Statistics & stats) { + inline void _RoutingStepWithStats(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, int *_upperbound, _Statistics & stats) { const NodeID node = _forwardHeap->DeleteMin(); stats.deleteMins++; const unsigned int distance = _forwardHeap->GetKey(node); @@ -367,9 +333,9 @@ private: assert(source != target); //find edge first. typename GraphT::EdgeIterator smallestEdge = SPECIAL_EDGEID; - EdgeWeight smallestWeight = UINT_MAX; + int smallestWeight = INT_MAX; for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(source);eit < _graph->EndEdges(source);eit++){ - const EdgeWeight weight = _graph->GetEdgeData(eit).distance; + const int weight = _graph->GetEdgeData(eit).distance; if(_graph->GetTarget(eit) == target && weight < smallestWeight && _graph->GetEdgeData(eit).forward){ smallestEdge = eit; smallestWeight = weight; @@ -378,7 +344,7 @@ private: if(smallestEdge == SPECIAL_EDGEID){ for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(target);eit < _graph->EndEdges(target);eit++){ - const EdgeWeight weight = _graph->GetEdgeData(eit).distance; + const int weight = _graph->GetEdgeData(eit).distance; if(_graph->GetTarget(eit) == source && weight < smallestWeight && _graph->GetEdgeData(eit).backward){ smallestEdge = eit; smallestWeight = weight; @@ -387,7 +353,7 @@ private: } - assert(smallestWeight != SPECIAL_EDGEID); + assert(smallestWeight != INT_MAX); const EdgeData& ed = _graph->GetEdgeData(smallestEdge); // INFO( (ed.shortcut ? "SHRT: " : "ORIG: ") << ed.distance << "," << ed.via); @@ -398,7 +364,7 @@ private: return false; } else { assert(!ed.shortcut); - path.push_back(_PathData(ed.via) ); + path.push_back(_PathData(ed.via, ed.nameID1, ed.turnInstruction, ed.distance) ); return true; } } diff --git a/Plugins/BaseDescriptor.h b/Plugins/BaseDescriptor.h index 55f5c7fc6..6a79302e6 100644 --- a/Plugins/BaseDescriptor.h +++ b/Plugins/BaseDescriptor.h @@ -30,7 +30,6 @@ or see http://www.gnu.org/licenses/agpl.txt. #include "../typedefs.h" #include "../DataStructures/ExtractorStructs.h" #include "../DataStructures/HashTable.h" -#include "../DataStructures/PolylineCompressor.h" #include "../Util/StringUtil.h" #include "RawRouteData.h" @@ -51,65 +50,30 @@ static double GetAngleBetweenTwoEdges(const _Coordinate& A, const _Coordinate& C return angle; } -struct RouteSummary { +struct _RouteSummary { std::string lengthString; std::string durationString; std::string startName; std::string destName; - RouteSummary() : lengthString("0"), durationString("0"), startName("unknown street"), destName("unknown street") {} + _RouteSummary() : lengthString("0"), durationString("0"), startName("unknown street"), destName("unknown street") {} void BuildDurationAndLengthStrings(double distance, unsigned time) { //compute distance/duration for route summary std::ostringstream s; s << 10*(round(distance/10.)); lengthString = s.str(); - int travelTime = 60*(time/60.) + 1; + int travelTime = time/10 + 1; s.str(""); s << travelTime; durationString = s.str(); } }; -struct DirectionOfInstruction { - std::string direction; - std::string shortDirection; -}; - -struct DescriptorState { - _Coordinate currentCoordinate, nextCoordinate, previousCoordinate, tmpCoord, startOfSegmentCoordinate; - std::string routeGeometryString; - std::string routeInstructionString; - unsigned lastNameID, currentNameID, geometryCounter, startIndexOfGeometry; - double entireDistance, distanceOfInstruction, durationOfInstruction; - - DescriptorState() : lastNameID(0), currentNameID(0), geometryCounter(0), startIndexOfGeometry(0), entireDistance(0.), distanceOfInstruction(0.), durationOfInstruction(0.) {}; - double GetAngleBetweenCoordinates() const { - return GetAngleBetweenTwoEdges(previousCoordinate, currentCoordinate, nextCoordinate); - } - bool CurrentAndPreviousNameIDsEqual() const { - return lastNameID == currentNameID; - } - void SetStartOfSegment() { - startOfSegmentCoordinate = nextCoordinate; - entireDistance += distanceOfInstruction; - lastNameID = currentNameID; - distanceOfInstruction = 0; - startIndexOfGeometry = geometryCounter-1; - } - void PrintCoordinates() { -#ifdef DEBUG - std::cout << "prev: " << previousCoordinate << ", curr: " << currentCoordinate << ", next: " << nextCoordinate << std::endl; -#endif - } -}; - struct _DescriptorConfig { _DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {} bool instructions; bool geometry; bool encodeGeometry; unsigned short z; - - PolylineCompressor pc; }; template @@ -122,86 +86,4 @@ public: virtual void SetConfig(const _DescriptorConfig & config) = 0; }; -static inline void getDirectionOfInstruction(double angle, DirectionOfInstruction & dirInst) { - if(angle >= 23 && angle < 67) { - dirInst.direction = "southeast"; - dirInst.shortDirection = "SE"; - return; - } - if(angle >= 67 && angle < 113) { - dirInst.direction = "south"; - dirInst.shortDirection = "S"; - return; - } - if(angle >= 113 && angle < 158) { - dirInst.direction = "southwest"; - dirInst.shortDirection = "SW"; - return; - } - if(angle >= 158 && angle < 202) { - dirInst.direction = "west"; - dirInst.shortDirection = "W"; - return; - } - if(angle >= 202 && angle < 248) { - dirInst.direction = "northwest"; - dirInst.shortDirection = "NW"; - return; - } - if(angle >= 248 && angle < 292) { - dirInst.direction = "north"; - dirInst.shortDirection = "N"; - return; - } - if(angle >= 292 && angle < 336) { - dirInst.direction = "northeast"; - dirInst.shortDirection = "NE"; - return; - } - dirInst.direction = "East"; - dirInst.shortDirection = "E"; - return; -} - -static inline void getTurnDirectionOfInstruction(double angle, std::string & output) { - if(angle >= 23 && angle < 67) { - output = "Turn sharp right"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - if (angle >= 67 && angle < 113) { - output = "Turn right"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - if (angle >= 113 && angle < 158) { - output = "Bear right"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - - if (angle >= 158 && angle < 202) { - output = "Continue"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - if (angle >= 202 && angle < 248) { - output = "Bear left"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - if (angle >= 248 && angle < 292) { - output = "Turn left"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - if (angle >= 292 && angle < 336) { - output = "Turn sharp left"; -// cout << "angle " << angle << "-> " << output << endl; - return; - } - output = "U-Turn"; -// cout << "angle " << angle << "-> " << output << endl; -} - #endif /* BASE_DESCRIPTOR_H_ */ diff --git a/Plugins/JSONDescriptor.h b/Plugins/JSONDescriptor.h index 6faf3b75a..f3214291f 100644 --- a/Plugins/JSONDescriptor.h +++ b/Plugins/JSONDescriptor.h @@ -24,44 +24,47 @@ or see http://www.gnu.org/licenses/agpl.txt. #include #include "BaseDescriptor.h" -#include "../DataStructures/PolylineCompressor.h" +#include "../DataStructures/JSONDescriptionFactory.h" +#include "../Util/StringUtil.h" template class JSONDescriptor : public BaseDescriptor{ private: _DescriptorConfig config; - RouteSummary summary; - DirectionOfInstruction directionOfInstruction; - DescriptorState descriptorState; + _RouteSummary summary; + JSONDescriptionFactory descriptionFactory; std::string tmp; - vector<_Coordinate> polyline; + _Coordinate current; public: JSONDescriptor() {} void SetConfig(const _DescriptorConfig & c) { config = c; } - void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) { + void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned durationOfTrip) { WriteHeaderToOutput(reply.content); //We do not need to do much, if there is no route ;-) - if(distance != UINT_MAX && rawRoute.routeSegments.size() > 0) { + //INFO("Starting at " << sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID) << ", id: " << phantomNodes.startPhantom.nodeBasedEdgeNameID); + //INFO("Arriving at " << sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID) << ", id: " << phantomNodes.startPhantom.nodeBasedEdgeNameID); + + if(durationOfTrip != INT_MAX && rawRoute.routeSegments.size() > 0) { + summary.startName = sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID); + summary.destName = sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID); + summary.BuildDurationAndLengthStrings(0, durationOfTrip); reply.content += "0," "\"status_message\": \"Found route between points\","; - - //Put first segment of route into geometry - polyline.push_back(phantomNodes.startPhantom.location); - + descriptionFactory.AddToPolyline(phantomNodes.startPhantom.location); for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) { const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx]; BOOST_FOREACH(_PathData pathData, path) { - _Coordinate current; sEngine.GetCoordinatesForNodeID(pathData.node, current); - polyline.push_back(current); -// INFO(pathData.node << " at " << current.lat << "," << current.lon); - //INFO("routed over node: " << pathData.node); + descriptionFactory.AppendSegment(pathData, current); + if(pathData.turnInstruction != 0) { + INFO("Turn on " << sEngine.GetEscapedNameForNameID(pathData.nameID) << ", turnID: " << pathData.turnInstruction ); + } } } - polyline.push_back(phantomNodes.targetPhantom.location); + descriptionFactory.AddToPolyline(phantomNodes.targetPhantom.location); } else { //no route found reply.content += "207," @@ -85,11 +88,9 @@ public: reply.content += "\"route_geometry\": "; if(config.geometry) { if(config.encodeGeometry) - config.pc.printEncodedString(polyline, descriptorState.routeGeometryString); + descriptionFactory.AppendEncodedPolylineString(reply.content); else - config.pc.printUnencodedString(polyline, descriptorState.routeGeometryString); - - reply.content += descriptorState.routeGeometryString; + descriptionFactory.AppendUnencodedPolylineString(reply.content); } else { reply.content += "[]"; } @@ -97,7 +98,7 @@ public: reply.content += "," "\"route_instructions\": ["; if(config.instructions) - reply.content += descriptorState.routeInstructionString; + descriptionFactory.AppendRouteInstructionString(reply.content); reply.content += "],"; //list all viapoints so that the client may display it reply.content += "\"via_points\":["; @@ -116,48 +117,6 @@ public: "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\""; reply.content += "}"; } -private: - void appendInstructionNameToString(const std::string & nameOfStreet, const std::string & instructionOrDirection, std::string &output, bool firstAdvice = false) { - output += "["; - if(config.instructions) { - output += "\""; - if(firstAdvice) { - output += "Head "; - } - output += instructionOrDirection; - output += "\",\""; - output += nameOfStreet; - output += "\","; - } - } - - void appendInstructionLengthToString(unsigned length, std::string &output) { - if(config.instructions){ - std::string tmpDistance; - intToString(10*(round(length/10.)), tmpDistance); - output += tmpDistance; - output += ","; - intToString(descriptorState.startIndexOfGeometry, tmp); - output += tmp; - output += ","; - intToString(descriptorState.durationOfInstruction, tmp); - output += tmp; - output += ","; - output += "\""; - output += tmpDistance; - output += "\","; - double angle = descriptorState.GetAngleBetweenCoordinates(); - DirectionOfInstruction direction; - getDirectionOfInstruction(angle, direction); - output += "\""; - output += direction.shortDirection; - output += "\","; - std::stringstream numberString; - numberString << fixed << setprecision(2) << angle; - output += numberString.str(); - } - output += "]"; - } void WriteHeaderToOutput(std::string & output) { output += "{" diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 0e617b063..3bbee20df 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -65,7 +65,7 @@ public: } virtual ~ViaRoutePlugin() { - DELETE( searchEngine ); + DELETE( searchEngine ); } std::string GetDescriptor() { return pluginDescriptorString; } @@ -101,7 +101,6 @@ public: } rawRoute.rawViaNodeCoordinates.push_back(startCoord); - INFO("[debug] number of vianodes: " << routeParameters.viaPoints.size()); for(unsigned i = 0; i < routeParameters.viaPoints.size(); i++) { textCoord = split (routeParameters.viaPoints[i], ','); if(textCoord.size() != 2) { @@ -123,7 +122,7 @@ public: bool errorOccurredFlag = false; for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); i++) { - searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i]); + searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i]); if(!rawRoute.rawViaNodeCoordinates[i].isSet()) { errorOccurredFlag = true; } @@ -132,29 +131,47 @@ public: rawRoute.Resize(); unsigned distance = 0; - for(unsigned i = 0; i < phantomNodeVector.size()-1 && !errorOccurredFlag; i++) { - PhantomNodes segmentPhantomNodes; - segmentPhantomNodes.startPhantom = phantomNodeVector[i]; - segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1]; - INFO(segmentPhantomNodes); - std::vector< _PathData > path; - unsigned distanceOfSegment = searchEngine->ComputeRoute(segmentPhantomNodes, path); - if(UINT_MAX == distanceOfSegment ) { - errorOccurredFlag = true; - INFO( "Error occurred, path not found" ); - distance = UINT_MAX; - break; - } else { - distance += distanceOfSegment; + //single route or via point routing + if(0 == routeParameters.viaPoints.size()) { + PhantomNodes segmentPhantomNodes; + segmentPhantomNodes.startPhantom = phantomNodeVector[0]; + segmentPhantomNodes.targetPhantom = phantomNodeVector[1]; + std::vector< _PathData > path; + distance = searchEngine->ComputeRoute(segmentPhantomNodes, path); + + if(UINT_MAX == distance ) { + INFO( "Error occurred, single path not found" ); } //put segments at correct position of routes raw data - rawRoute.segmentEndCoordinates[i] = (segmentPhantomNodes); - rawRoute.routeSegments[i] = path; - } + rawRoute.segmentEndCoordinates[0] = (segmentPhantomNodes); + rawRoute.routeSegments[0] = path; + } else { + //Getting the shortest via path is a dynamic programming problem and is solved as such. + for(unsigned i = 0; i < phantomNodeVector.size()-1 && !errorOccurredFlag; i++) { + PhantomNodes segmentPhantomNodes; + segmentPhantomNodes.startPhantom = phantomNodeVector[i]; + segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1]; + INFO(segmentPhantomNodes); + std::vector< _PathData > path; + unsigned distanceOfSegment = searchEngine->ComputeRoute(segmentPhantomNodes, path); - INFO("Found path of length: " << distance); + if(UINT_MAX == distanceOfSegment ) { + errorOccurredFlag = true; + INFO( "Error occurred, via path not found" ); + distance = UINT_MAX; + break; + } else { + distance += distanceOfSegment; + } + + //put segments at correct position of routes raw data + rawRoute.segmentEndCoordinates[i] = (segmentPhantomNodes); + rawRoute.routeSegments[i] = path; + } + } + INFO("Found path of length " << distance); reply.status = http::Reply::ok; @@ -215,13 +232,6 @@ public: reply.headers[0].value = tmp; switch(descriptorType){ case 0: - reply.headers[1].name = "Content-Type"; - reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8"; - reply.headers[2].name = "Content-Disposition"; - reply.headers[2].value = "attachment; filename=\"route.kml\""; - - break; - case 1: if("" != JSONParameter){ reply.headers[1].name = "Content-Type"; reply.headers[1].value = "text/javascript"; @@ -235,7 +245,7 @@ public: } break; - case 2: + case 1: reply.headers[1].name = "Content-Type"; reply.headers[1].value = "application/gpx+xml; charset=UTF-8"; reply.headers[2].name = "Content-Disposition"; @@ -243,10 +253,17 @@ public: break; default: - reply.headers[1].name = "Content-Type"; - reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8"; - reply.headers[2].name = "Content-Disposition"; - reply.headers[2].value = "attachment; filename=\"route.kml\""; + if("" != JSONParameter){ + reply.headers[1].name = "Content-Type"; + reply.headers[1].value = "text/javascript"; + reply.headers[2].name = "Content-Disposition"; + reply.headers[2].value = "attachment; filename=\"route.js\""; + } else { + reply.headers[1].name = "Content-Type"; + reply.headers[1].value = "application/x-javascript"; + reply.headers[2].name = "Content-Disposition"; + reply.headers[2].value = "attachment; filename=\"route.json\""; + } break; }