Add first nodes with negative weights
This commit is contained in:
parent
caf8cd701e
commit
9a6cf7b991
@ -130,12 +130,12 @@ void EdgeBasedGraphFactory::Run() {
|
|||||||
if( !isTurnProhibited ) { //only add an edge if turn is not prohibited
|
if( !isTurnProhibited ) { //only add an edge if turn is not prohibited
|
||||||
//new costs for edge based edge (e1, e2) = cost (e1) + tc(e1,e2)
|
//new costs for edge based edge (e1, e2) = cost (e1) + tc(e1,e2)
|
||||||
const _NodeBasedDynamicGraph::NodeIterator edgeBasedSource = _nodeBasedGraph->GetEdgeData(e1).edgeBasedNodeID;
|
const _NodeBasedDynamicGraph::NodeIterator edgeBasedSource = _nodeBasedGraph->GetEdgeData(e1).edgeBasedNodeID;
|
||||||
// INFO("edgeBasedSource: " << edgeBasedSource);
|
// INFO("edgeBasedSource: " << edgeBasedSource);
|
||||||
if(edgeBasedSource > _nodeBasedGraph->GetNumberOfEdges()) {
|
if(edgeBasedSource > _nodeBasedGraph->GetNumberOfEdges()) {
|
||||||
ERR("edgeBasedTarget" << edgeBasedSource << ">" << _nodeBasedGraph->GetNumberOfEdges());
|
ERR("edgeBasedTarget" << edgeBasedSource << ">" << _nodeBasedGraph->GetNumberOfEdges());
|
||||||
}
|
}
|
||||||
const _NodeBasedDynamicGraph::NodeIterator edgeBasedTarget = _nodeBasedGraph->GetEdgeData(e2).edgeBasedNodeID;
|
const _NodeBasedDynamicGraph::NodeIterator edgeBasedTarget = _nodeBasedGraph->GetEdgeData(e2).edgeBasedNodeID;
|
||||||
// INFO("edgeBasedTarget: " << edgeBasedTarget);
|
// INFO("edgeBasedTarget: " << edgeBasedTarget);
|
||||||
if(edgeBasedTarget > _nodeBasedGraph->GetNumberOfEdges()) {
|
if(edgeBasedTarget > _nodeBasedGraph->GetNumberOfEdges()) {
|
||||||
ERR("edgeBasedTarget" << edgeBasedTarget << ">" << _nodeBasedGraph->GetNumberOfEdges());
|
ERR("edgeBasedTarget" << edgeBasedTarget << ">" << _nodeBasedGraph->GetNumberOfEdges());
|
||||||
}
|
}
|
||||||
@ -150,9 +150,14 @@ void EdgeBasedGraphFactory::Run() {
|
|||||||
newEdge.data.via = v;
|
newEdge.data.via = v;
|
||||||
newEdge.data.nameID1 = _nodeBasedGraph->GetEdgeData(e1).middleName.nameID;
|
newEdge.data.nameID1 = _nodeBasedGraph->GetEdgeData(e1).middleName.nameID;
|
||||||
newEdge.data.nameID2 = _nodeBasedGraph->GetEdgeData(e2).middleName.nameID;
|
newEdge.data.nameID2 = _nodeBasedGraph->GetEdgeData(e2).middleName.nameID;
|
||||||
//Todo: turn type angeben
|
//Todo: turn instruction angeben
|
||||||
newEdge.data.turnInstruction = 0;
|
|
||||||
|
|
||||||
|
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
|
//create Edge for NearestNeighborlookup
|
||||||
edgeBasedEdges.push_back(newEdge);
|
edgeBasedEdges.push_back(newEdge);
|
||||||
EdgeBasedNode currentNode;
|
EdgeBasedNode currentNode;
|
||||||
@ -164,15 +169,7 @@ void EdgeBasedGraphFactory::Run() {
|
|||||||
currentNode.lat2 = inputNodeInfoList[v].lat;
|
currentNode.lat2 = inputNodeInfoList[v].lat;
|
||||||
currentNode.lon2 = inputNodeInfoList[v].lon;
|
currentNode.lon2 = inputNodeInfoList[v].lon;
|
||||||
currentNode.id = edgeBasedSource;
|
currentNode.id = edgeBasedSource;
|
||||||
edgeBasedNodes.push_back(currentNode);
|
currentNode.weight = _nodeBasedGraph->GetEdgeData(e1).distance;
|
||||||
}
|
|
||||||
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;
|
|
||||||
edgeBasedNodes.push_back(currentNode);
|
edgeBasedNodes.push_back(currentNode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,7 +42,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct _NodeBasedEdgeData {
|
struct _NodeBasedEdgeData {
|
||||||
unsigned distance;
|
int distance;
|
||||||
unsigned edgeBasedNodeID;
|
unsigned edgeBasedNodeID;
|
||||||
unsigned originalEdges;
|
unsigned originalEdges;
|
||||||
bool shortcut;
|
bool shortcut;
|
||||||
@ -53,7 +53,7 @@ private:
|
|||||||
} data;
|
} data;
|
||||||
|
|
||||||
struct _EdgeBasedEdgeData {
|
struct _EdgeBasedEdgeData {
|
||||||
unsigned distance;
|
int distance;
|
||||||
unsigned via;
|
unsigned via;
|
||||||
unsigned nameID1;
|
unsigned nameID1;
|
||||||
unsigned nameID2;
|
unsigned nameID2;
|
||||||
@ -79,6 +79,7 @@ public:
|
|||||||
int lon2;
|
int lon2;
|
||||||
NodeID id;
|
NodeID id;
|
||||||
NodeID nameID;
|
NodeID nameID;
|
||||||
|
unsigned weight;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DynamicGraph< _EdgeBasedEdgeData> _EdgeBasedDynamicGraph;
|
typedef DynamicGraph< _EdgeBasedEdgeData> _EdgeBasedDynamicGraph;
|
||||||
|
@ -27,11 +27,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
struct _PathData {
|
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;
|
NodeID node;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
unsigned turnInstruction;
|
|
||||||
unsigned lengthOfSegment;
|
unsigned lengthOfSegment;
|
||||||
|
short turnInstruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::unordered_map<std::string, NodeID> StringMap;
|
typedef boost::unordered_map<std::string, NodeID> StringMap;
|
||||||
|
@ -22,9 +22,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#define GRIDEDGE_H_
|
#define GRIDEDGE_H_
|
||||||
|
|
||||||
struct _GridEdge {
|
struct _GridEdge {
|
||||||
_GridEdge(NodeID n, _Coordinate sc, _Coordinate tc) : edgeBasedNode(n), startCoord(sc), targetCoord(tc) {}
|
_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) {}
|
_GridEdge() : edgeBasedNode(UINT_MAX), nameID(UINT_MAX), weight(INT_MAX) {}
|
||||||
NodeID edgeBasedNode;
|
NodeID edgeBasedNode;
|
||||||
|
NodeID nameID;
|
||||||
|
int weight;
|
||||||
_Coordinate startCoord;
|
_Coordinate startCoord;
|
||||||
_Coordinate targetCoord;
|
_Coordinate targetCoord;
|
||||||
};
|
};
|
||||||
|
@ -198,7 +198,7 @@ public:
|
|||||||
int tlat = 100000*lat2y(edge.lat2/100000.);
|
int tlat = 100000*lat2y(edge.lat2/100000.);
|
||||||
int tlon = edge.lon2;
|
int tlon = edge.lon2;
|
||||||
AddEdge( _GridEdge(
|
AddEdge( _GridEdge(
|
||||||
edge.id, edge.nameID,
|
edge.id, edge.nameID, edge.weight,
|
||||||
_Coordinate(slat, slon),
|
_Coordinate(slat, slon),
|
||||||
_Coordinate(tlat, tlon) )
|
_Coordinate(tlat, tlon) )
|
||||||
);
|
);
|
||||||
@ -300,26 +300,55 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Coordinate tmp;
|
_GridEdge smallestEdge;
|
||||||
|
_Coordinate tmp, newEndpoint;
|
||||||
double dist = (numeric_limits<double>::max)();
|
double dist = (numeric_limits<double>::max)();
|
||||||
BOOST_FOREACH(_GridEdge candidate, candidates) {
|
BOOST_FOREACH(_GridEdge candidate, candidates) {
|
||||||
double r = 0.;
|
double r = 0.;
|
||||||
double tmpDist = ComputeDistance(startCoord, candidate.startCoord, candidate.targetCoord, tmp, &r);
|
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.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) {
|
if(tmpDist < dist) {
|
||||||
resultNode.isBidirected = false;
|
resultNode.Reset();
|
||||||
resultNode.edgeBasedNode = candidate.edgeBasedNode;
|
resultNode.edgeBasedNode = candidate.edgeBasedNode;
|
||||||
resultNode.nodeBasedEdgeNameID = candidate.nameID;
|
resultNode.nodeBasedEdgeNameID = candidate.nameID;
|
||||||
resultNode.ratio = r;
|
resultNode.weight1 = candidate.weight;
|
||||||
dist = tmpDist;
|
dist = tmpDist;
|
||||||
resultNode.location.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
|
resultNode.location.lat = round(100000*(y2lat(static_cast<double>(tmp.lat)/100000.)));
|
||||||
resultNode.location.lon = tmp.lon;
|
resultNode.location.lon = tmp.lon;
|
||||||
foundNode = true;
|
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;
|
return foundNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,6 +404,15 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
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<GridEntry>& entriesWithSameRAMIndex, unsigned fileOffset ) {
|
unsigned FillCell(std::vector<GridEntry>& entriesWithSameRAMIndex, unsigned fileOffset ) {
|
||||||
vector<char> * tmpBuffer = new vector<char>();
|
vector<char> * tmpBuffer = new vector<char>();
|
||||||
|
@ -24,18 +24,21 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
|
|
||||||
struct PhantomNode {
|
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;
|
bool isBidirected;
|
||||||
NodeID edgeBasedNode;
|
NodeID edgeBasedNode;
|
||||||
unsigned nodeBasedEdgeNameID;
|
unsigned nodeBasedEdgeNameID;
|
||||||
double ratio;
|
int weight1;
|
||||||
|
int weight2;
|
||||||
_Coordinate location;
|
_Coordinate location;
|
||||||
void Reset() {
|
void Reset() {
|
||||||
|
isBidirected = false;
|
||||||
edgeBasedNode = UINT_MAX;
|
edgeBasedNode = UINT_MAX;
|
||||||
ratio = 1.;
|
nodeBasedEdgeNameID = UINT_MAX;
|
||||||
|
weight1 = INT_MAX;
|
||||||
|
weight2 = INT_MAX;
|
||||||
location.Reset();
|
location.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PhantomNodes {
|
struct PhantomNodes {
|
||||||
|
@ -25,6 +25,8 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#include "ExtractorStructs.h"
|
#include "ExtractorStructs.h"
|
||||||
|
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
class PolylineCompressor {
|
class PolylineCompressor {
|
||||||
private:
|
private:
|
||||||
inline void encodeVectorSignedNumber(vector<int> & numbers, string & output) {
|
inline void encodeVectorSignedNumber(vector<int> & numbers, string & output) {
|
||||||
|
@ -76,10 +76,6 @@ public:
|
|||||||
result.lon = nodeHelpDesk->getLongitudeOfNode(id);
|
result.lon = nodeHelpDesk->getLongitudeOfNode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int numberOfNodes() const {
|
|
||||||
return nodeHelpDesk->getNumberOfNodes();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InitializeThreadLocalStorageIfNecessary() {
|
inline void InitializeThreadLocalStorageIfNecessary() {
|
||||||
if(!_forwardHeap.get())
|
if(!_forwardHeap.get())
|
||||||
_forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes()));
|
_forwardHeap.reset(new BinaryHeap< NodeID, NodeID, int, _HeapData >(nodeHelpDesk->getNumberOfNodes()));
|
||||||
@ -92,8 +88,8 @@ public:
|
|||||||
_backwardHeap->Clear();
|
_backwardHeap->Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ComputeRoute(PhantomNodes & phantomNodes, vector<_PathData> & path) {
|
int ComputeRoute(PhantomNodes & phantomNodes, vector<_PathData> & path) {
|
||||||
unsigned int _upperbound = UINT_MAX;
|
int _upperbound = INT_MAX;
|
||||||
if(!phantomNodes.AtLeastOnePhantomNodeIsUINTMAX())
|
if(!phantomNodes.AtLeastOnePhantomNodeIsUINTMAX())
|
||||||
return _upperbound;
|
return _upperbound;
|
||||||
|
|
||||||
@ -105,19 +101,19 @@ public:
|
|||||||
return _upperbound;
|
return _upperbound;
|
||||||
}
|
}
|
||||||
//insert start and/or target node of start edge
|
//insert start and/or target node of start edge
|
||||||
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, 0, phantomNodes.startPhantom.edgeBasedNode);
|
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, -phantomNodes.startPhantom.weight1, phantomNodes.startPhantom.edgeBasedNode);
|
||||||
// INFO("Inserting start1: " << phantomNodes.startPhantom.edgeBasedNode);
|
// INFO("[FORW] Inserting node " << phantomNodes.startPhantom.edgeBasedNode << " at distance " << -phantomNodes.startPhantom.weight1);
|
||||||
if(phantomNodes.startPhantom.isBidirected) {
|
if(phantomNodes.startPhantom.isBidirected) {
|
||||||
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode+1, 0, phantomNodes.startPhantom.edgeBasedNode+1);
|
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode+1, -phantomNodes.startPhantom.weight2, phantomNodes.startPhantom.edgeBasedNode+1);
|
||||||
// INFO("Inserting start2: " << 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
|
//insert start and/or target node of target edge id
|
||||||
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode, 0, phantomNodes.targetPhantom.edgeBasedNode);
|
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode, -phantomNodes.targetPhantom.weight1, phantomNodes.targetPhantom.edgeBasedNode);
|
||||||
// INFO("Inserting target1: " << phantomNodes.targetPhantom.edgeBasedNode);
|
// INFO("[BACK] Inserting node " << phantomNodes.targetPhantom.edgeBasedNode << " at distance " << -phantomNodes.targetPhantom.weight1);
|
||||||
if(phantomNodes.targetPhantom.isBidirected) {
|
if(phantomNodes.targetPhantom.isBidirected) {
|
||||||
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode+1, 0, phantomNodes.targetPhantom.edgeBasedNode+1);
|
_backwardHeap->Insert(phantomNodes.targetPhantom.edgeBasedNode+1, -phantomNodes.targetPhantom.weight2, phantomNodes.targetPhantom.edgeBasedNode+1);
|
||||||
// INFO("Inserting target2: " << phantomNodes.targetPhantom.edgeBasedNode+1);
|
// INFO("[BACK] Inserting node " << phantomNodes.targetPhantom.edgeBasedNode+1 << " at distance " << -phantomNodes.targetPhantom.weight2);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(_forwardHeap->Size() + _backwardHeap->Size() > 0){
|
while(_forwardHeap->Size() + _backwardHeap->Size() > 0){
|
||||||
@ -130,7 +126,7 @@ public:
|
|||||||
}
|
}
|
||||||
// INFO("bidirectional search iteration ended: " << _forwardHeap->Size() << "," << _backwardHeap->Size() << ", dist: " << _upperbound);
|
// INFO("bidirectional search iteration ended: " << _forwardHeap->Size() << "," << _backwardHeap->Size() << ", dist: " << _upperbound);
|
||||||
|
|
||||||
if ( _upperbound == UINT_MAX ) {
|
if ( _upperbound == INT_MAX ) {
|
||||||
return _upperbound;
|
return _upperbound;
|
||||||
}
|
}
|
||||||
NodeID pathNode = middle;
|
NodeID pathNode = middle;
|
||||||
@ -156,7 +152,7 @@ public:
|
|||||||
unsigned int ComputeDistanceBetweenNodes(NodeID start, NodeID target) {
|
unsigned int ComputeDistanceBetweenNodes(NodeID start, NodeID target) {
|
||||||
InitializeThreadLocalStorageIfNecessary();
|
InitializeThreadLocalStorageIfNecessary();
|
||||||
NodeID middle(UINT_MAX);
|
NodeID middle(UINT_MAX);
|
||||||
unsigned int _upperbound = UINT_MAX;
|
int _upperbound = INT_MAX;
|
||||||
_forwardHeap->Insert(start, 0, start);
|
_forwardHeap->Insert(start, 0, start);
|
||||||
_backwardHeap->Insert(target, 0, target);
|
_backwardHeap->Insert(target, 0, target);
|
||||||
while(_forwardHeap->Size() + _backwardHeap->Size() > 0){
|
while(_forwardHeap->Size() + _backwardHeap->Size() > 0){
|
||||||
@ -167,14 +163,13 @@ public:
|
|||||||
_RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound);
|
_RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _upperbound;
|
return _upperbound;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ComputeDistanceBetweenNodesWithStats(NodeID start, NodeID target, _Statistics & stats) {
|
unsigned int ComputeDistanceBetweenNodesWithStats(NodeID start, NodeID target, _Statistics & stats) {
|
||||||
InitializeThreadLocalStorageIfNecessary();
|
InitializeThreadLocalStorageIfNecessary();
|
||||||
NodeID middle(UINT_MAX);
|
NodeID middle(UINT_MAX);
|
||||||
unsigned int _upperbound = UINT_MAX;
|
int _upperbound = INT_MAX;
|
||||||
_forwardHeap->Insert(start, 0, start);
|
_forwardHeap->Insert(start, 0, start);
|
||||||
_backwardHeap->Insert(target, 0, target);
|
_backwardHeap->Insert(target, 0, target);
|
||||||
stats.insertedNodes += 2;
|
stats.insertedNodes += 2;
|
||||||
@ -190,11 +185,6 @@ public:
|
|||||||
return _upperbound;
|
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) {
|
inline bool FindRoutingStarts(const _Coordinate & start, const _Coordinate & target, PhantomNodes & routingStarts) {
|
||||||
nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
|
nodeHelpDesk->FindRoutingStarts(start, target, routingStarts);
|
||||||
return true;
|
return true;
|
||||||
@ -205,7 +195,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline NodeID GetNameIDForOriginDestinationNodeID(NodeID s, NodeID t) const {
|
inline NodeID GetNameIDForOriginDestinationNodeID(NodeID s, NodeID t) const {
|
||||||
//INFO("Getting nameID for s=" << s << " and t=" << t);
|
|
||||||
if(s == t)
|
if(s == t)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -213,7 +202,6 @@ public:
|
|||||||
if(e == UINT_MAX)
|
if(e == UINT_MAX)
|
||||||
e = _graph->FindEdge( t, s );
|
e = _graph->FindEdge( t, s );
|
||||||
if(UINT_MAX == e) {
|
if(UINT_MAX == e) {
|
||||||
// INFO("edge not found for start " << s << ", target " << t)
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
assert(e != UINT_MAX);
|
assert(e != UINT_MAX);
|
||||||
@ -221,45 +209,22 @@ public:
|
|||||||
return ed.via;
|
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 {
|
inline std::string GetEscapedNameForNameID(const NodeID nameID) const {
|
||||||
return ((nameID >= _names->size() || nameID == 0) ? std::string("") : HTMLEntitize(_names->at(nameID)));
|
return ((nameID >= _names->size() || nameID == 0) ? std::string("") : HTMLEntitize(_names->at(nameID)));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline short GetTypeOfEdgeForOriginDestinationNodeID(NodeID s, NodeID t) const {
|
inline std::string GetEscapedNameForEdgeBasedEdgeID(const unsigned edgeID) 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const unsigned nameID = _graph->GetEdgeData(edgeID).nameID1;
|
||||||
|
return GetEscapedNameForNameID(nameID);
|
||||||
|
}
|
||||||
private:
|
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 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)){
|
if(_backwardHeap->WasInserted(node)){
|
||||||
const unsigned int newDistance = _backwardHeap->GetKey(node) + distance;
|
const int newDistance = _backwardHeap->GetKey(node) + distance;
|
||||||
if(newDistance < *_upperbound){
|
if(newDistance < *_upperbound){
|
||||||
*middle = node;
|
*middle = node;
|
||||||
*_upperbound = newDistance;
|
*_upperbound = newDistance;
|
||||||
@ -270,9 +235,9 @@ private:
|
|||||||
_forwardHeap->DeleteAll();
|
_forwardHeap->DeleteAll();
|
||||||
return;
|
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 NodeID to = _graph->GetTarget(edge);
|
||||||
const EdgeWeight edgeWeight = _graph->GetEdgeData(edge).distance;
|
const int edgeWeight = _graph->GetEdgeData(edge).distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
|
|
||||||
@ -286,19 +251,20 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
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 NodeID to = _graph->GetTarget(edge);
|
||||||
const EdgeWeight edgeWeight = _graph->GetEdgeData(edge).distance;
|
const int edgeWeight = _graph->GetEdgeData(edge).distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
const int toDistance = distance + edgeWeight;
|
|
||||||
assert(toDistance > 0);
|
|
||||||
|
|
||||||
bool forwardDirectionFlag = (forwardDirection ? _graph->GetEdgeData(edge).forward : _graph->GetEdgeData(edge).backward );
|
bool forwardDirectionFlag = (forwardDirection ? _graph->GetEdgeData(edge).forward : _graph->GetEdgeData(edge).backward );
|
||||||
if(forwardDirectionFlag) {
|
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
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if ( !_forwardHeap->WasInserted( to ) ) {
|
if ( !_forwardHeap->WasInserted( to ) ) {
|
||||||
|
// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " inserting node " << to << " at distance " << toDistance);
|
||||||
_forwardHeap->Insert( to, toDistance, node );
|
_forwardHeap->Insert( to, toDistance, node );
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//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();
|
const NodeID node = _forwardHeap->DeleteMin();
|
||||||
stats.deleteMins++;
|
stats.deleteMins++;
|
||||||
const unsigned int distance = _forwardHeap->GetKey(node);
|
const unsigned int distance = _forwardHeap->GetKey(node);
|
||||||
@ -367,9 +333,9 @@ private:
|
|||||||
assert(source != target);
|
assert(source != target);
|
||||||
//find edge first.
|
//find edge first.
|
||||||
typename GraphT::EdgeIterator smallestEdge = SPECIAL_EDGEID;
|
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++){
|
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){
|
if(_graph->GetTarget(eit) == target && weight < smallestWeight && _graph->GetEdgeData(eit).forward){
|
||||||
smallestEdge = eit;
|
smallestEdge = eit;
|
||||||
smallestWeight = weight;
|
smallestWeight = weight;
|
||||||
@ -378,7 +344,7 @@ private:
|
|||||||
|
|
||||||
if(smallestEdge == SPECIAL_EDGEID){
|
if(smallestEdge == SPECIAL_EDGEID){
|
||||||
for(typename GraphT::EdgeIterator eit = _graph->BeginEdges(target);eit < _graph->EndEdges(target);eit++){
|
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){
|
if(_graph->GetTarget(eit) == source && weight < smallestWeight && _graph->GetEdgeData(eit).backward){
|
||||||
smallestEdge = eit;
|
smallestEdge = eit;
|
||||||
smallestWeight = weight;
|
smallestWeight = weight;
|
||||||
@ -387,7 +353,7 @@ private:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(smallestWeight != SPECIAL_EDGEID);
|
assert(smallestWeight != INT_MAX);
|
||||||
|
|
||||||
const EdgeData& ed = _graph->GetEdgeData(smallestEdge);
|
const EdgeData& ed = _graph->GetEdgeData(smallestEdge);
|
||||||
// INFO( (ed.shortcut ? "SHRT: " : "ORIG: ") << ed.distance << "," << ed.via);
|
// INFO( (ed.shortcut ? "SHRT: " : "ORIG: ") << ed.distance << "," << ed.via);
|
||||||
@ -398,7 +364,7 @@ private:
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
assert(!ed.shortcut);
|
assert(!ed.shortcut);
|
||||||
path.push_back(_PathData(ed.via) );
|
path.push_back(_PathData(ed.via, ed.nameID1, ed.turnInstruction, ed.distance) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
#include "../DataStructures/ExtractorStructs.h"
|
#include "../DataStructures/ExtractorStructs.h"
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/PolylineCompressor.h"
|
|
||||||
#include "../Util/StringUtil.h"
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
#include "RawRouteData.h"
|
#include "RawRouteData.h"
|
||||||
@ -51,65 +50,30 @@ static double GetAngleBetweenTwoEdges(const _Coordinate& A, const _Coordinate& C
|
|||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RouteSummary {
|
struct _RouteSummary {
|
||||||
std::string lengthString;
|
std::string lengthString;
|
||||||
std::string durationString;
|
std::string durationString;
|
||||||
std::string startName;
|
std::string startName;
|
||||||
std::string destName;
|
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) {
|
void BuildDurationAndLengthStrings(double distance, unsigned time) {
|
||||||
//compute distance/duration for route summary
|
//compute distance/duration for route summary
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << 10*(round(distance/10.));
|
s << 10*(round(distance/10.));
|
||||||
lengthString = s.str();
|
lengthString = s.str();
|
||||||
int travelTime = 60*(time/60.) + 1;
|
int travelTime = time/10 + 1;
|
||||||
s.str("");
|
s.str("");
|
||||||
s << travelTime;
|
s << travelTime;
|
||||||
durationString = s.str();
|
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 {
|
struct _DescriptorConfig {
|
||||||
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {}
|
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {}
|
||||||
bool instructions;
|
bool instructions;
|
||||||
bool geometry;
|
bool geometry;
|
||||||
bool encodeGeometry;
|
bool encodeGeometry;
|
||||||
unsigned short z;
|
unsigned short z;
|
||||||
|
|
||||||
PolylineCompressor pc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class SearchEngineT>
|
template<class SearchEngineT>
|
||||||
@ -122,86 +86,4 @@ public:
|
|||||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
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_ */
|
#endif /* BASE_DESCRIPTOR_H_ */
|
||||||
|
@ -24,44 +24,47 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
#include "../DataStructures/PolylineCompressor.h"
|
#include "../DataStructures/JSONDescriptionFactory.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
template<class SearchEngineT>
|
template<class SearchEngineT>
|
||||||
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||||
private:
|
private:
|
||||||
_DescriptorConfig config;
|
_DescriptorConfig config;
|
||||||
RouteSummary summary;
|
_RouteSummary summary;
|
||||||
DirectionOfInstruction directionOfInstruction;
|
JSONDescriptionFactory descriptionFactory;
|
||||||
DescriptorState descriptorState;
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
vector<_Coordinate> polyline;
|
_Coordinate current;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONDescriptor() {}
|
JSONDescriptor() {}
|
||||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
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);
|
WriteHeaderToOutput(reply.content);
|
||||||
//We do not need to do much, if there is no route ;-)
|
//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,"
|
reply.content += "0,"
|
||||||
"\"status_message\": \"Found route between points\",";
|
"\"status_message\": \"Found route between points\",";
|
||||||
|
descriptionFactory.AddToPolyline(phantomNodes.startPhantom.location);
|
||||||
//Put first segment of route into geometry
|
|
||||||
polyline.push_back(phantomNodes.startPhantom.location);
|
|
||||||
|
|
||||||
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
|
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
|
||||||
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
|
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
|
||||||
BOOST_FOREACH(_PathData pathData, path) {
|
BOOST_FOREACH(_PathData pathData, path) {
|
||||||
_Coordinate current;
|
|
||||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||||
polyline.push_back(current);
|
descriptionFactory.AppendSegment(pathData, current);
|
||||||
// INFO(pathData.node << " at " << current.lat << "," << current.lon);
|
if(pathData.turnInstruction != 0) {
|
||||||
//INFO("routed over node: " << pathData.node);
|
INFO("Turn on " << sEngine.GetEscapedNameForNameID(pathData.nameID) << ", turnID: " << pathData.turnInstruction );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
polyline.push_back(phantomNodes.targetPhantom.location);
|
descriptionFactory.AddToPolyline(phantomNodes.targetPhantom.location);
|
||||||
} else {
|
} else {
|
||||||
//no route found
|
//no route found
|
||||||
reply.content += "207,"
|
reply.content += "207,"
|
||||||
@ -85,11 +88,9 @@ public:
|
|||||||
reply.content += "\"route_geometry\": ";
|
reply.content += "\"route_geometry\": ";
|
||||||
if(config.geometry) {
|
if(config.geometry) {
|
||||||
if(config.encodeGeometry)
|
if(config.encodeGeometry)
|
||||||
config.pc.printEncodedString(polyline, descriptorState.routeGeometryString);
|
descriptionFactory.AppendEncodedPolylineString(reply.content);
|
||||||
else
|
else
|
||||||
config.pc.printUnencodedString(polyline, descriptorState.routeGeometryString);
|
descriptionFactory.AppendUnencodedPolylineString(reply.content);
|
||||||
|
|
||||||
reply.content += descriptorState.routeGeometryString;
|
|
||||||
} else {
|
} else {
|
||||||
reply.content += "[]";
|
reply.content += "[]";
|
||||||
}
|
}
|
||||||
@ -97,7 +98,7 @@ public:
|
|||||||
reply.content += ","
|
reply.content += ","
|
||||||
"\"route_instructions\": [";
|
"\"route_instructions\": [";
|
||||||
if(config.instructions)
|
if(config.instructions)
|
||||||
reply.content += descriptorState.routeInstructionString;
|
descriptionFactory.AppendRouteInstructionString(reply.content);
|
||||||
reply.content += "],";
|
reply.content += "],";
|
||||||
//list all viapoints so that the client may display it
|
//list all viapoints so that the client may display it
|
||||||
reply.content += "\"via_points\":[";
|
reply.content += "\"via_points\":[";
|
||||||
@ -116,48 +117,6 @@ public:
|
|||||||
"\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\"";
|
"\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\"";
|
||||||
reply.content += "}";
|
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) {
|
void WriteHeaderToOutput(std::string & output) {
|
||||||
output += "{"
|
output += "{"
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {
|
virtual ~ViaRoutePlugin() {
|
||||||
DELETE( searchEngine );
|
DELETE( searchEngine );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDescriptor() { return pluginDescriptorString; }
|
std::string GetDescriptor() { return pluginDescriptorString; }
|
||||||
@ -101,7 +101,6 @@ public:
|
|||||||
}
|
}
|
||||||
rawRoute.rawViaNodeCoordinates.push_back(startCoord);
|
rawRoute.rawViaNodeCoordinates.push_back(startCoord);
|
||||||
|
|
||||||
INFO("[debug] number of vianodes: " << routeParameters.viaPoints.size());
|
|
||||||
for(unsigned i = 0; i < routeParameters.viaPoints.size(); i++) {
|
for(unsigned i = 0; i < routeParameters.viaPoints.size(); i++) {
|
||||||
textCoord = split (routeParameters.viaPoints[i], ',');
|
textCoord = split (routeParameters.viaPoints[i], ',');
|
||||||
if(textCoord.size() != 2) {
|
if(textCoord.size() != 2) {
|
||||||
@ -123,7 +122,7 @@ public:
|
|||||||
bool errorOccurredFlag = false;
|
bool errorOccurredFlag = false;
|
||||||
|
|
||||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); i++) {
|
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()) {
|
if(!rawRoute.rawViaNodeCoordinates[i].isSet()) {
|
||||||
errorOccurredFlag = true;
|
errorOccurredFlag = true;
|
||||||
}
|
}
|
||||||
@ -132,29 +131,47 @@ public:
|
|||||||
rawRoute.Resize();
|
rawRoute.Resize();
|
||||||
unsigned distance = 0;
|
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 ) {
|
//single route or via point routing
|
||||||
errorOccurredFlag = true;
|
if(0 == routeParameters.viaPoints.size()) {
|
||||||
INFO( "Error occurred, path not found" );
|
PhantomNodes segmentPhantomNodes;
|
||||||
distance = UINT_MAX;
|
segmentPhantomNodes.startPhantom = phantomNodeVector[0];
|
||||||
break;
|
segmentPhantomNodes.targetPhantom = phantomNodeVector[1];
|
||||||
} else {
|
std::vector< _PathData > path;
|
||||||
distance += distanceOfSegment;
|
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
|
//put segments at correct position of routes raw data
|
||||||
rawRoute.segmentEndCoordinates[i] = (segmentPhantomNodes);
|
rawRoute.segmentEndCoordinates[0] = (segmentPhantomNodes);
|
||||||
rawRoute.routeSegments[i] = path;
|
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;
|
reply.status = http::Reply::ok;
|
||||||
|
|
||||||
@ -215,13 +232,6 @@ public:
|
|||||||
reply.headers[0].value = tmp;
|
reply.headers[0].value = tmp;
|
||||||
switch(descriptorType){
|
switch(descriptorType){
|
||||||
case 0:
|
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){
|
if("" != JSONParameter){
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "text/javascript";
|
reply.headers[1].value = "text/javascript";
|
||||||
@ -235,7 +245,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
reply.headers[1].name = "Content-Type";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[2].name = "Content-Disposition";
|
||||||
@ -243,10 +253,17 @@ public:
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
reply.headers[1].name = "Content-Type";
|
if("" != JSONParameter){
|
||||||
reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8";
|
reply.headers[1].name = "Content-Type";
|
||||||
reply.headers[2].name = "Content-Disposition";
|
reply.headers[1].value = "text/javascript";
|
||||||
reply.headers[2].value = "attachment; filename=\"route.kml\"";
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user