Moved descriptors into their own folder.
This commit is contained in:
parent
95bcfa3dce
commit
14c999fc82
@ -24,13 +24,14 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/unordered_map.hpp>
|
#include <boost/unordered_map.hpp>
|
||||||
|
#include "../typedefs.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
struct _PathData {
|
struct _PathData {
|
||||||
_PathData(NodeID no, unsigned na, unsigned tu, unsigned le) : node(no), nameID(na), lengthOfSegment(le), turnInstruction(tu) { }
|
_PathData(NodeID no, unsigned na, unsigned tu, unsigned dur) : node(no), nameID(na), durationOfSegment(dur), turnInstruction(tu) { }
|
||||||
NodeID node;
|
NodeID node;
|
||||||
unsigned nameID;
|
unsigned nameID;
|
||||||
unsigned lengthOfSegment;
|
unsigned durationOfSegment;
|
||||||
short turnInstruction;
|
short turnInstruction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,28 +32,28 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
#include "../typedefs.h"
|
#include "../typedefs.h"
|
||||||
|
|
||||||
struct _HeapData {
|
struct _HeapData {
|
||||||
NodeID parent;
|
NodeID parent;
|
||||||
_HeapData( NodeID p ) : parent(p) { }
|
_HeapData( NodeID p ) : parent(p) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Statistics {
|
struct _Statistics {
|
||||||
_Statistics () : insertedNodes(0), stalledNodes(0), meetingNodes(0), deleteMins(0), decreasedNodes(0), oqf(0), eqf(0), df(0), preprocTime(0) {};
|
_Statistics () : insertedNodes(0), stalledNodes(0), meetingNodes(0), deleteMins(0), decreasedNodes(0), oqf(0), eqf(0), df(0), preprocTime(0) {};
|
||||||
void Reset() {
|
void Reset() {
|
||||||
insertedNodes = 0;
|
insertedNodes = 0;
|
||||||
stalledNodes = 0;
|
stalledNodes = 0;
|
||||||
meetingNodes = 0;
|
meetingNodes = 0;
|
||||||
deleteMins = 0;
|
deleteMins = 0;
|
||||||
decreasedNodes = 0;
|
decreasedNodes = 0;
|
||||||
}
|
}
|
||||||
unsigned insertedNodes;
|
unsigned insertedNodes;
|
||||||
unsigned stalledNodes;
|
unsigned stalledNodes;
|
||||||
unsigned meetingNodes;
|
unsigned meetingNodes;
|
||||||
unsigned deleteMins;
|
unsigned deleteMins;
|
||||||
unsigned decreasedNodes;
|
unsigned decreasedNodes;
|
||||||
unsigned oqf;
|
unsigned oqf;
|
||||||
unsigned eqf;
|
unsigned eqf;
|
||||||
unsigned df;
|
unsigned df;
|
||||||
double preprocTime;
|
double preprocTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData > > HeapPtr;
|
typedef boost::thread_specific_ptr<BinaryHeap< NodeID, NodeID, int, _HeapData > > HeapPtr;
|
||||||
@ -63,18 +63,18 @@ class SearchEngine {
|
|||||||
private:
|
private:
|
||||||
const GraphT * _graph;
|
const GraphT * _graph;
|
||||||
NodeInformationHelpDesk * nodeHelpDesk;
|
NodeInformationHelpDesk * nodeHelpDesk;
|
||||||
std::vector<string> * _names;
|
std::vector<string> * _names;
|
||||||
static HeapPtr _forwardHeap;
|
static HeapPtr _forwardHeap;
|
||||||
static HeapPtr _backwardHeap;
|
static HeapPtr _backwardHeap;
|
||||||
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
|
inline double absDouble(double input) { if(input < 0) return input*(-1); else return input;}
|
||||||
public:
|
public:
|
||||||
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, vector<string> * n = new vector<string>()) : _graph(g), nodeHelpDesk(nh), _names(n) {}
|
SearchEngine(GraphT * g, NodeInformationHelpDesk * nh, vector<string> * n = new vector<string>()) : _graph(g), nodeHelpDesk(nh), _names(n) {}
|
||||||
~SearchEngine() {}
|
~SearchEngine() {}
|
||||||
|
|
||||||
inline const void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
|
inline const void GetCoordinatesForNodeID(NodeID id, _Coordinate& result) const {
|
||||||
result.lat = nodeHelpDesk->getLatitudeOfNode(id);
|
result.lat = nodeHelpDesk->getLatitudeOfNode(id);
|
||||||
result.lon = nodeHelpDesk->getLongitudeOfNode(id);
|
result.lon = nodeHelpDesk->getLongitudeOfNode(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void InitializeThreadLocalStorageIfNecessary() {
|
inline void InitializeThreadLocalStorageIfNecessary() {
|
||||||
if(!_forwardHeap.get())
|
if(!_forwardHeap.get())
|
||||||
@ -98,22 +98,23 @@ public:
|
|||||||
if(phantomNodes.PhantomsAreOnSameNodeBasedEdge()){
|
if(phantomNodes.PhantomsAreOnSameNodeBasedEdge()){
|
||||||
//TODO: Hier behandeln, dass Start und Ziel auf der gleichen Originalkante liegen
|
//TODO: Hier behandeln, dass Start und Ziel auf der gleichen Originalkante liegen
|
||||||
INFO("TODO: Start and target are on same edge")
|
INFO("TODO: Start and target are on same edge")
|
||||||
return _upperbound;
|
return _upperbound;
|
||||||
}
|
}
|
||||||
|
double time1 = get_timestamp();
|
||||||
//insert start and/or target node of start edge
|
//insert start and/or target node of start edge
|
||||||
_forwardHeap->Insert(phantomNodes.startPhantom.edgeBasedNode, -phantomNodes.startPhantom.weight1, 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);
|
// 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, -phantomNodes.startPhantom.weight2, 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);
|
// 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, -phantomNodes.targetPhantom.weight1, 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);
|
// 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, -phantomNodes.targetPhantom.weight2, 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);
|
// 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){
|
||||||
@ -124,28 +125,31 @@ public:
|
|||||||
_RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound);
|
_RoutingStep(_backwardHeap, _forwardHeap, false, &middle, &_upperbound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// INFO("bidirectional search iteration ended: " << _forwardHeap->Size() << "," << _backwardHeap->Size() << ", dist: " << _upperbound);
|
// INFO("bidirectional search iteration ended: " << _forwardHeap->Size() << "," << _backwardHeap->Size() << ", dist: " << _upperbound);
|
||||||
|
double time2 = get_timestamp();
|
||||||
if ( _upperbound == INT_MAX ) {
|
if ( _upperbound == INT_MAX ) {
|
||||||
return _upperbound;
|
return _upperbound;
|
||||||
}
|
}
|
||||||
NodeID pathNode = middle;
|
NodeID pathNode = middle;
|
||||||
deque<NodeID> packedPath;
|
deque<NodeID> packedPath;
|
||||||
while(phantomNodes.startPhantom.edgeBasedNode != pathNode && (!phantomNodes.startPhantom.isBidirected || phantomNodes.startPhantom.edgeBasedNode+1 != pathNode) ) {
|
while(phantomNodes.startPhantom.edgeBasedNode != pathNode && (!phantomNodes.startPhantom.isBidirected || phantomNodes.startPhantom.edgeBasedNode+1 != pathNode) ) {
|
||||||
pathNode = _forwardHeap->GetData(pathNode).parent;
|
pathNode = _forwardHeap->GetData(pathNode).parent;
|
||||||
packedPath.push_front(pathNode);
|
packedPath.push_front(pathNode);
|
||||||
}
|
}
|
||||||
// INFO("Finished getting packed forward path: " << packedPath.size());
|
// INFO("Finished getting packed forward path: " << packedPath.size());
|
||||||
packedPath.push_back(middle);
|
packedPath.push_back(middle);
|
||||||
pathNode = middle;
|
pathNode = middle;
|
||||||
while(phantomNodes.targetPhantom.edgeBasedNode != pathNode && (!phantomNodes.targetPhantom.isBidirected || phantomNodes.targetPhantom.edgeBasedNode+1 != pathNode)) {
|
while(phantomNodes.targetPhantom.edgeBasedNode != pathNode && (!phantomNodes.targetPhantom.isBidirected || phantomNodes.targetPhantom.edgeBasedNode+1 != pathNode)) {
|
||||||
pathNode = _backwardHeap->GetData(pathNode).parent;
|
pathNode = _backwardHeap->GetData(pathNode).parent;
|
||||||
packedPath.push_back(pathNode);
|
packedPath.push_back(pathNode);
|
||||||
}
|
}
|
||||||
// INFO("Finished getting packed path: " << packedPath.size());
|
// INFO("Finished getting packed path: " << packedPath.size());
|
||||||
for(deque<NodeID>::size_type i = 0;i < packedPath.size() - 1;i++){
|
for(deque<NodeID>::size_type i = 0;i < packedPath.size() - 1;i++){
|
||||||
_UnpackEdge(packedPath[i], packedPath[i + 1], path);
|
_UnpackEdge(packedPath[i], packedPath[i + 1], path);
|
||||||
}
|
}
|
||||||
|
double time3 = get_timestamp();
|
||||||
|
INFO("Path computed in " << (time2-time1)*1000 << "msec, unpacked in " << (time3-time2)*1000 << "msec");
|
||||||
|
|
||||||
return _upperbound;
|
return _upperbound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,10 +204,10 @@ public:
|
|||||||
|
|
||||||
EdgeID e = _graph->FindEdge(s, t);
|
EdgeID e = _graph->FindEdge(s, t);
|
||||||
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) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
assert(e != UINT_MAX);
|
assert(e != UINT_MAX);
|
||||||
const EdgeData ed = _graph->GetEdgeData(e);
|
const EdgeData ed = _graph->GetEdgeData(e);
|
||||||
return ed.via;
|
return ed.via;
|
||||||
@ -222,7 +226,7 @@ private:
|
|||||||
inline void _RoutingStep(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, 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 int distance = _forwardHeap->GetKey(node);
|
const int distance = _forwardHeap->GetKey(node);
|
||||||
// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " settling " << node << " with distance " << distance);
|
// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " settling " << node << " with distance " << distance);
|
||||||
if(_backwardHeap->WasInserted(node)){
|
if(_backwardHeap->WasInserted(node)){
|
||||||
const int newDistance = _backwardHeap->GetKey(node) + distance;
|
const int newDistance = _backwardHeap->GetKey(node) + distance;
|
||||||
if(newDistance < *_upperbound){
|
if(newDistance < *_upperbound){
|
||||||
@ -235,46 +239,48 @@ private:
|
|||||||
_forwardHeap->DeleteAll();
|
_forwardHeap->DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) {
|
|
||||||
const NodeID to = _graph->GetTarget(edge);
|
|
||||||
const int edgeWeight = _graph->GetEdgeData(edge).distance;
|
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
|
||||||
|
|
||||||
//Stalling
|
|
||||||
bool backwardDirectionFlag = (!forwardDirection) ? _graph->GetEdgeData(edge).forward : _graph->GetEdgeData(edge).backward;
|
|
||||||
if(_forwardHeap->WasInserted( to )) {
|
|
||||||
if(backwardDirectionFlag) {
|
|
||||||
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
|
|
||||||
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 EdgeData & data = _graph->GetEdgeData(edge);
|
||||||
const int edgeWeight = _graph->GetEdgeData(edge).distance;
|
bool backwardDirectionFlag = (!forwardDirection) ? data.forward : data.backward;
|
||||||
|
if(backwardDirectionFlag) {
|
||||||
|
const NodeID to = _graph->GetTarget(edge);
|
||||||
|
const int edgeWeight = data.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 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
|
//Stalling
|
||||||
if ( !_forwardHeap->WasInserted( to ) ) {
|
if(_forwardHeap->WasInserted( to )) {
|
||||||
// INFO((forwardDirection ? "[FORW]" : "[BACK]") << " inserting node " << to << " at distance " << toDistance);
|
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
|
||||||
_forwardHeap->Insert( to, toDistance, node );
|
return;
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
}
|
||||||
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
|
}
|
||||||
_forwardHeap->GetData( to ).parent = node;
|
}
|
||||||
_forwardHeap->DecreaseKey( to, toDistance );
|
|
||||||
//new parent
|
for ( typename GraphT::EdgeIterator edge = _graph->BeginEdges( node ); edge < _graph->EndEdges(node); edge++ ) {
|
||||||
}
|
const EdgeData & data = _graph->GetEdgeData(edge);
|
||||||
}
|
bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward );
|
||||||
}
|
if(forwardDirectionFlag) {
|
||||||
|
|
||||||
|
const NodeID to = _graph->GetTarget(edge);
|
||||||
|
const int edgeWeight = data.distance;
|
||||||
|
|
||||||
|
assert( edgeWeight > 0 );
|
||||||
|
const int toDistance = distance + edgeWeight;
|
||||||
|
|
||||||
|
//New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if ( !_forwardHeap->WasInserted( to ) ) {
|
||||||
|
_forwardHeap->Insert( to, toDistance, node );
|
||||||
|
}
|
||||||
|
//Found a shorter Path -> Update distance
|
||||||
|
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
|
||||||
|
_forwardHeap->GetData( to ).parent = node;
|
||||||
|
_forwardHeap->DecreaseKey( to, toDistance );
|
||||||
|
//new parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void _RoutingStepWithStats(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, int *_upperbound, _Statistics & stats) {
|
inline void _RoutingStepWithStats(HeapPtr & _forwardHeap, HeapPtr & _backwardHeap, const bool & forwardDirection, NodeID *middle, int *_upperbound, _Statistics & stats) {
|
||||||
@ -295,38 +301,38 @@ private:
|
|||||||
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 EdgeData& ed = _graph->GetEdgeData(edge);
|
const EdgeData& ed = _graph->GetEdgeData(edge);
|
||||||
const NodeID to = _graph->GetTarget(edge);
|
const NodeID to = _graph->GetTarget(edge);
|
||||||
const EdgeWeight edgeWeight = ed.distance;
|
const EdgeWeight edgeWeight = ed.distance;
|
||||||
|
|
||||||
assert( edgeWeight > 0 );
|
assert( edgeWeight > 0 );
|
||||||
const int toDistance = distance + edgeWeight;
|
const int toDistance = distance + edgeWeight;
|
||||||
|
|
||||||
//Stalling
|
//Stalling
|
||||||
if(_forwardHeap->WasInserted( to )) {
|
if(_forwardHeap->WasInserted( to )) {
|
||||||
if(!forwardDirection ? ed.forward : ed.backward) {
|
if(!forwardDirection ? ed.forward : ed.backward) {
|
||||||
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
|
if(_forwardHeap->GetKey( to ) + edgeWeight < distance) {
|
||||||
stats.stalledNodes++;
|
stats.stalledNodes++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(forwardDirection ? ed.forward : ed.backward ) {
|
if(forwardDirection ? ed.forward : ed.backward ) {
|
||||||
//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 ) ) {
|
||||||
_forwardHeap->Insert( to, toDistance, node );
|
_forwardHeap->Insert( to, toDistance, node );
|
||||||
stats.insertedNodes++;
|
stats.insertedNodes++;
|
||||||
}
|
}
|
||||||
//Found a shorter Path -> Update distance
|
//Found a shorter Path -> Update distance
|
||||||
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
|
else if ( toDistance < _forwardHeap->GetKey( to ) ) {
|
||||||
_forwardHeap->GetData( to ).parent = node;
|
_forwardHeap->GetData( to ).parent = node;
|
||||||
_forwardHeap->DecreaseKey( to, toDistance );
|
_forwardHeap->DecreaseKey( to, toDistance );
|
||||||
stats.decreasedNodes++;
|
stats.decreasedNodes++;
|
||||||
//new parent
|
//new parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool _UnpackEdge(const NodeID source, const NodeID target, std::vector<_PathData> & path) {
|
inline bool _UnpackEdge(const NodeID source, const NodeID target, std::vector<_PathData> & path) {
|
||||||
@ -355,19 +361,19 @@ private:
|
|||||||
|
|
||||||
assert(smallestWeight != INT_MAX);
|
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);
|
||||||
if(ed.shortcut) {//unpack
|
if(ed.shortcut) {//unpack
|
||||||
const NodeID middle = ed.via;
|
const NodeID middle = ed.via;
|
||||||
_UnpackEdge(source, middle, path);
|
_UnpackEdge(source, middle, path);
|
||||||
_UnpackEdge(middle, target, path);
|
_UnpackEdge(middle, target, path);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
assert(!ed.shortcut);
|
assert(!ed.shortcut);
|
||||||
path.push_back(_PathData(ed.via, ed.nameID1, ed.turnInstruction, ed.distance) );
|
path.push_back(_PathData(ed.via, ed.nameID1, ed.turnInstruction, ed.distance) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_forwardHeap;
|
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_forwardHeap;
|
||||||
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_backwardHeap;
|
template<class EdgeData, class GraphT> HeapPtr SearchEngine<EdgeData, GraphT>::_backwardHeap;
|
||||||
|
89
Descriptors/BaseDescriptor.h
Normal file
89
Descriptors/BaseDescriptor.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
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 BASE_DESCRIPTOR_H_
|
||||||
|
#define BASE_DESCRIPTOR_H_
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "../DataStructures/ExtractorStructs.h"
|
||||||
|
#include "../DataStructures/HashTable.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
#include "../Plugins/RawRouteData.h"
|
||||||
|
|
||||||
|
static double areaThresholds[19] = { 5000, 5000, 5000, 5000, 5000, 2500, 2000, 1500, 800, 400, 250, 150, 100, 75, 25, 20, 10, 5, 0 };
|
||||||
|
|
||||||
|
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||||
|
static double GetAngleBetweenTwoEdges(const _Coordinate& A, const _Coordinate& C, const _Coordinate& B) {
|
||||||
|
int v1x = A.lon - C.lon;
|
||||||
|
int v1y = A.lat - C.lat;
|
||||||
|
int v2x = B.lon - C.lon;
|
||||||
|
int v2y = B.lat - C.lat;
|
||||||
|
|
||||||
|
double angle = (atan2((double)v2y,v2x) - atan2((double)v1y,v1x) )*180/M_PI;
|
||||||
|
while(angle < 0)
|
||||||
|
angle += 360;
|
||||||
|
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
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") {}
|
||||||
|
void BuildDurationAndLengthStrings(unsigned distance, unsigned time) {
|
||||||
|
//compute distance/duration for route summary
|
||||||
|
std::ostringstream s;
|
||||||
|
s << 10*(round(distance/10.));
|
||||||
|
lengthString = s.str();
|
||||||
|
int travelTime = time/10 + 1;
|
||||||
|
s.str("");
|
||||||
|
s << travelTime;
|
||||||
|
durationString = s.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _DescriptorConfig {
|
||||||
|
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {}
|
||||||
|
bool instructions;
|
||||||
|
bool geometry;
|
||||||
|
bool encodeGeometry;
|
||||||
|
unsigned short z;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class SearchEngineT>
|
||||||
|
class BaseDescriptor {
|
||||||
|
public:
|
||||||
|
BaseDescriptor() { }
|
||||||
|
//Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||||
|
virtual ~BaseDescriptor() { }
|
||||||
|
virtual void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) = 0;
|
||||||
|
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* BASE_DESCRIPTOR_H_ */
|
115
Descriptors/DescriptionFactory.cpp
Normal file
115
Descriptors/DescriptionFactory.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
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 <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include "../typedefs.h"
|
||||||
|
#include "DescriptionFactory.h"
|
||||||
|
|
||||||
|
DescriptionFactory::DescriptionFactory() { }
|
||||||
|
|
||||||
|
DescriptionFactory::~DescriptionFactory() { }
|
||||||
|
|
||||||
|
double DescriptionFactory::GetAngleBetweenCoordinates() const {
|
||||||
|
return 0.;//GetAngleBetweenTwoEdges(previousCoordinate, currentCoordinate, nextCoordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::SetStartSegment(const PhantomNode & _startPhantom) {
|
||||||
|
startPhantom = _startPhantom;
|
||||||
|
AppendSegment(_startPhantom.location, _PathData(0, _startPhantom.nodeBasedEdgeNameID, 10, _startPhantom.weight1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::SetEndSegment(const PhantomNode & _targetPhantom) {
|
||||||
|
targetPhantom = _targetPhantom;
|
||||||
|
AppendSegment(_targetPhantom.location, _PathData(0, _targetPhantom.nodeBasedEdgeNameID, 0, _targetPhantom.weight1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendSegment(const _Coordinate & coordinate, const _PathData & data ) {
|
||||||
|
//Segment information has following format:
|
||||||
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
|
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||||
|
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
|
||||||
|
// (_Coordinate & loc, NodeID nam, unsigned len, unsigned dur, short tInstr)
|
||||||
|
|
||||||
|
//Is a new instruction necessary?
|
||||||
|
//yes: data.turnInstruction != 0;
|
||||||
|
//no: data.turnInstruction == 0;
|
||||||
|
pathDescription.push_back(SegmentInformation(coordinate, data.nameID, 0, data.durationOfSegment, data.turnInstruction) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendRouteInstructionString(std::string & output) {
|
||||||
|
output += "[\"Turn left\",\"High Street\",200,0,10,\"200m\",\"NE\",22.5]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendEncodedPolylineString(std::string & output, bool isEncoded) {
|
||||||
|
if(isEncoded)
|
||||||
|
pc.printEncodedString(pathDescription, output);
|
||||||
|
else
|
||||||
|
pc.printUnencodedString(pathDescription, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendEncodedPolylineString(std::string &output) {
|
||||||
|
pc.printEncodedString(pathDescription, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionFactory::AppendUnencodedPolylineString(std::string &output) {
|
||||||
|
pc.printUnencodedString(pathDescription, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned DescriptionFactory::Run() {
|
||||||
|
if(0 == pathDescription.size())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned entireLength = 0;
|
||||||
|
/** starts at index 1 */
|
||||||
|
pathDescription[0].length = 0;
|
||||||
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
pathDescription[i].length = ApproximateDistance(pathDescription[i-1].location, pathDescription[i].location);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned lengthOfSegment = 0;
|
||||||
|
unsigned durationOfSegment = 0;
|
||||||
|
unsigned indexOfSegmentBegin = 0;
|
||||||
|
|
||||||
|
for(unsigned i = 1; i < pathDescription.size(); ++i) {
|
||||||
|
entireLength += pathDescription[i].length;
|
||||||
|
lengthOfSegment += pathDescription[i].length;
|
||||||
|
durationOfSegment += pathDescription[i].duration;
|
||||||
|
pathDescription[indexOfSegmentBegin].length = lengthOfSegment;
|
||||||
|
pathDescription[indexOfSegmentBegin].duration = durationOfSegment;
|
||||||
|
if(pathDescription[i].turnInstruction != 0) {
|
||||||
|
//INFO("Turn after " << lengthOfSegment << "m into way with name id " << segment.nameID);
|
||||||
|
assert(pathDescription[i].necessary);
|
||||||
|
lengthOfSegment = 0;
|
||||||
|
durationOfSegment = 0;
|
||||||
|
indexOfSegmentBegin = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Generalize poly line
|
||||||
|
BOOST_FOREACH(SegmentInformation & segment, pathDescription) {
|
||||||
|
//TODO: Replace me by real generalization
|
||||||
|
segment.necessary = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//fix what needs to be fixed else
|
||||||
|
return entireLength;
|
||||||
|
}
|
176
Descriptors/DescriptionFactory.h
Normal file
176
Descriptors/DescriptionFactory.h
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DESCRIPTIONFACTORY_H_
|
||||||
|
#define DESCRIPTIONFACTORY_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../Algorithms/PolylineCompressor.h"
|
||||||
|
#include "../DataStructures/ExtractorStructs.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
|
||||||
|
/* This class is fed with all way segments in consecutive order
|
||||||
|
* and produces the description plus the encoded polyline */
|
||||||
|
|
||||||
|
class DescriptionFactory {
|
||||||
|
PolylineCompressor pc;
|
||||||
|
PhantomNode startPhantom, targetPhantom;
|
||||||
|
public:
|
||||||
|
//I know, declaring this public is considered bad. I'm lazy
|
||||||
|
std::vector <SegmentInformation> pathDescription;
|
||||||
|
DescriptionFactory();
|
||||||
|
virtual ~DescriptionFactory();
|
||||||
|
double GetAngleBetweenCoordinates() const;
|
||||||
|
void AppendEncodedPolylineString(std::string &output);
|
||||||
|
void AppendUnencodedPolylineString(std::string &output);
|
||||||
|
void AppendSegment(const _Coordinate & coordinate, const _PathData & data);
|
||||||
|
void AppendRouteInstructionString(std::string & output);
|
||||||
|
void SetStartSegment(const PhantomNode & startPhantom);
|
||||||
|
void SetEndSegment(const PhantomNode & startPhantom);
|
||||||
|
void AppendEncodedPolylineString(std::string & output, bool isEncoded);
|
||||||
|
unsigned Run();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
//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(descriptionFactory.startIndexOfGeometry, tmp);
|
||||||
|
// output += tmp;
|
||||||
|
// output += ",";
|
||||||
|
// intToString(descriptionFactory.durationOfInstruction, tmp);
|
||||||
|
// output += tmp;
|
||||||
|
// output += ",";
|
||||||
|
// output += "\"";
|
||||||
|
// output += tmpDistance;
|
||||||
|
// output += "\",";
|
||||||
|
// double angle = descriptionFactory.GetAngleBetweenCoordinates();
|
||||||
|
// DirectionOfInstruction direction;
|
||||||
|
// getDirectionOfInstruction(angle, direction);
|
||||||
|
// output += "\"";
|
||||||
|
// output += direction.shortDirection;
|
||||||
|
// output += "\",";
|
||||||
|
// std::stringstream numberString;
|
||||||
|
// numberString << fixed << setprecision(2) << angle;
|
||||||
|
// output += numberString.str();
|
||||||
|
// }
|
||||||
|
// output += "]";
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* DESCRIPTIONFACTORY_H_ */
|
67
Descriptors/GPXDescriptor.h
Normal file
67
Descriptors/GPXDescriptor.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GPX_DESCRIPTOR_H_
|
||||||
|
#define GPX_DESCRIPTOR_H_
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include "BaseDescriptor.h"
|
||||||
|
|
||||||
|
template<class SearchEngineT>
|
||||||
|
class GPXDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||||
|
private:
|
||||||
|
_DescriptorConfig config;
|
||||||
|
_Coordinate current;
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
public:
|
||||||
|
void SetConfig(const _DescriptorConfig& c) { config = c; }
|
||||||
|
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
|
||||||
|
reply.content += ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||||
|
reply.content += "<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||||
|
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||||
|
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||||
|
"\">";
|
||||||
|
reply.content += "<rte>";
|
||||||
|
if(distance != UINT_MAX && rawRoute.routeSegments.size()) {
|
||||||
|
convertInternalLatLonToString(phantomNodes.startPhantom.location.lat, tmp);
|
||||||
|
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||||
|
convertInternalLatLonToString(phantomNodes.startPhantom.location.lon, tmp);
|
||||||
|
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||||
|
|
||||||
|
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
|
||||||
|
BOOST_FOREACH(_PathData pathData, rawRoute.routeSegments[segmentIdx]) {
|
||||||
|
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||||
|
|
||||||
|
convertInternalLatLonToString(current.lat, tmp);
|
||||||
|
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||||
|
convertInternalLatLonToString(current.lon, tmp);
|
||||||
|
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lat, tmp);
|
||||||
|
reply.content += "<rtept lat=\"" + tmp + "\" ";
|
||||||
|
convertInternalLatLonToString(phantomNodes.targetPhantom.location.lon, tmp);
|
||||||
|
reply.content += "lon=\"" + tmp + "\"></rtept>";
|
||||||
|
}
|
||||||
|
reply.content += "</rte></gpx>";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif /* GPX_DESCRIPTOR_H_ */
|
154
Descriptors/JSONDescriptor.h
Normal file
154
Descriptors/JSONDescriptor.h
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef JSON_DESCRIPTOR_H_
|
||||||
|
#define JSON_DESCRIPTOR_H_
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
#include "BaseDescriptor.h"
|
||||||
|
#include "DescriptionFactory.h"
|
||||||
|
#include "../DataStructures/SegmentInformation.h"
|
||||||
|
#include "../DataStructures/TurnInstructions.h"
|
||||||
|
#include "../Util/StringUtil.h"
|
||||||
|
|
||||||
|
template<class SearchEngineT>
|
||||||
|
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||||
|
private:
|
||||||
|
_DescriptorConfig config;
|
||||||
|
_RouteSummary summary;
|
||||||
|
DescriptionFactory descriptionFactory;
|
||||||
|
std::string tmp;
|
||||||
|
_Coordinate current;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JSONDescriptor() {}
|
||||||
|
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
||||||
|
|
||||||
|
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(durationOfTrip != INT_MAX && rawRoute.routeSegments.size() > 0) {
|
||||||
|
summary.startName = sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID);
|
||||||
|
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||||
|
summary.destName = sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID);
|
||||||
|
reply.content += "0,"
|
||||||
|
"\"status_message\": \"Found route between points\",";
|
||||||
|
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
|
||||||
|
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
|
||||||
|
BOOST_FOREACH(_PathData pathData, path) {
|
||||||
|
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||||
|
descriptionFactory.AppendSegment(current, pathData );
|
||||||
|
}
|
||||||
|
//TODO: Add via points
|
||||||
|
}
|
||||||
|
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
|
||||||
|
} else {
|
||||||
|
//no route found
|
||||||
|
reply.content += "207,"
|
||||||
|
"\"status_message\": \"Cannot find route between points\",";
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.BuildDurationAndLengthStrings(descriptionFactory.Run(), durationOfTrip);
|
||||||
|
|
||||||
|
reply.content += "\"route_summary\": {"
|
||||||
|
"\"total_distance\":";
|
||||||
|
reply.content += summary.lengthString;
|
||||||
|
reply.content += ","
|
||||||
|
"\"total_time\":";
|
||||||
|
reply.content += summary.durationString;
|
||||||
|
reply.content += ","
|
||||||
|
"\"start_point\":\"";
|
||||||
|
reply.content += summary.startName;
|
||||||
|
reply.content += "\","
|
||||||
|
"\"end_point\":\"";
|
||||||
|
reply.content += summary.destName;
|
||||||
|
reply.content += "\"";
|
||||||
|
reply.content += "},";
|
||||||
|
reply.content += "\"route_geometry\": ";
|
||||||
|
if(config.geometry) {
|
||||||
|
if(config.encodeGeometry)
|
||||||
|
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
||||||
|
} else {
|
||||||
|
reply.content += "[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.content += ","
|
||||||
|
"\"route_instructions\": [";
|
||||||
|
if(config.instructions) {
|
||||||
|
unsigned prefixSumOfNecessarySegments = 0;
|
||||||
|
std::string tmpDist, tmpLength, tmp;
|
||||||
|
//Fetch data from Factory and generate a string from it.
|
||||||
|
BOOST_FOREACH(SegmentInformation segment, descriptionFactory.pathDescription) {
|
||||||
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||||
|
if(0 != segment.turnInstruction) {
|
||||||
|
if(0 != prefixSumOfNecessarySegments)
|
||||||
|
reply.content += ",";
|
||||||
|
reply.content += "[\"";
|
||||||
|
reply.content += TurnInstructions.TurnStrings[segment.turnInstruction];
|
||||||
|
reply.content += "\",\"";
|
||||||
|
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
|
||||||
|
reply.content += "\",";
|
||||||
|
intToString(segment.length, tmpDist);
|
||||||
|
reply.content += tmpDist;
|
||||||
|
reply.content += ",";
|
||||||
|
intToString(prefixSumOfNecessarySegments, tmpLength);
|
||||||
|
reply.content += tmpLength;
|
||||||
|
reply.content += ",";
|
||||||
|
intToString(segment.duration, tmp);
|
||||||
|
reply.content += ",\"";
|
||||||
|
reply.content += tmpLength;
|
||||||
|
//TODO: fix heading
|
||||||
|
reply.content += "\",\"NE\",22.5";
|
||||||
|
reply.content += "]";
|
||||||
|
}
|
||||||
|
if(segment.necessary)
|
||||||
|
++prefixSumOfNecessarySegments;
|
||||||
|
}
|
||||||
|
// descriptionFactory.AppendRouteInstructionString(reply.content);
|
||||||
|
|
||||||
|
}
|
||||||
|
reply.content += "],";
|
||||||
|
//list all viapoints so that the client may display it
|
||||||
|
reply.content += "\"via_points\":[";
|
||||||
|
for(unsigned segmentIdx = 1; (true == config.geometry) && (segmentIdx < rawRoute.segmentEndCoordinates.size()); segmentIdx++) {
|
||||||
|
if(segmentIdx > 1)
|
||||||
|
reply.content += ",";
|
||||||
|
reply.content += "[";
|
||||||
|
if(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location.isSet())
|
||||||
|
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, tmp);
|
||||||
|
else
|
||||||
|
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[segmentIdx], tmp);
|
||||||
|
reply.content += tmp;
|
||||||
|
reply.content += "]";
|
||||||
|
}
|
||||||
|
reply.content += "],"
|
||||||
|
"\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\"";
|
||||||
|
reply.content += "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteHeaderToOutput(std::string & output) {
|
||||||
|
output += "{"
|
||||||
|
"\"version\": 0.3,"
|
||||||
|
"\"status\":";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif /* JSON_DESCRIPTOR_H_ */
|
@ -29,11 +29,11 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
|||||||
|
|
||||||
#include "ObjectForPluginStruct.h"
|
#include "ObjectForPluginStruct.h"
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
|
||||||
#include "BasePlugin.h"
|
#include "BasePlugin.h"
|
||||||
#include "RouteParameters.h"
|
#include "RouteParameters.h"
|
||||||
#include "GPXDescriptor.h"
|
#include "../Descriptors/BaseDescriptor.h"
|
||||||
#include "JSONDescriptor.h"
|
#include "../Descriptors/GPXDescriptor.h"
|
||||||
|
#include "../Descriptors/JSONDescriptor.h"
|
||||||
|
|
||||||
#include "../DataStructures/HashTable.h"
|
#include "../DataStructures/HashTable.h"
|
||||||
#include "../DataStructures/StaticGraph.h"
|
#include "../DataStructures/StaticGraph.h"
|
||||||
@ -131,7 +131,6 @@ public:
|
|||||||
rawRoute.Resize();
|
rawRoute.Resize();
|
||||||
unsigned distance = 0;
|
unsigned distance = 0;
|
||||||
|
|
||||||
|
|
||||||
//single route or via point routing
|
//single route or via point routing
|
||||||
if(0 == routeParameters.viaPoints.size()) {
|
if(0 == routeParameters.viaPoints.size()) {
|
||||||
PhantomNodes segmentPhantomNodes;
|
PhantomNodes segmentPhantomNodes;
|
||||||
|
Loading…
Reference in New Issue
Block a user