Route description are generated
This commit is contained in:
parent
d874b51419
commit
e7439e92ed
@ -26,7 +26,6 @@
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "EdgeBasedGraphFactory.h"
|
||||
#include "../DataStructures/ExtractorStructs.h"
|
||||
|
||||
template<>
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(int nodes, std::vector<NodeBasedEdge> & inputEdges, std::vector<_Restriction> & irs, std::vector<NodeInfo> & nI)
|
||||
@ -149,15 +148,7 @@ void EdgeBasedGraphFactory::Run() {
|
||||
newEdge.data.backward = false;
|
||||
newEdge.data.via = v;
|
||||
newEdge.data.nameID = _nodeBasedGraph->GetEdgeData(e2).middleName.nameID;
|
||||
//newEdge.data.nameID2 = _nodeBasedGraph->GetEdgeData(e2).middleName.nameID;
|
||||
//Todo: turn instruction angeben
|
||||
|
||||
if(newEdge.data.nameID == _nodeBasedGraph->GetEdgeData(e1).middleName.nameID)
|
||||
newEdge.data.turnInstruction = 0;
|
||||
else {
|
||||
//TODO: Winkel berechnen und angepasste Anweisung geben.
|
||||
newEdge.data.turnInstruction = 1;
|
||||
}
|
||||
newEdge.data.turnInstruction = AnalyzeTurn(u, v, w);
|
||||
//create Edge for NearestNeighborlookup
|
||||
edgeBasedEdges.push_back(newEdge);
|
||||
EdgeBasedNode currentNode;
|
||||
@ -188,6 +179,19 @@ void EdgeBasedGraphFactory::Run() {
|
||||
INFO("Generated " << edgeBasedNodes.size() << " edge based nodes");
|
||||
}
|
||||
|
||||
short EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const {
|
||||
_NodeBasedDynamicGraph::EdgeIterator edge1 = _nodeBasedGraph->FindEdge(u, v);
|
||||
_NodeBasedDynamicGraph::EdgeIterator edge2 = _nodeBasedGraph->FindEdge(v, w);
|
||||
|
||||
_NodeBasedDynamicGraph::EdgeData data1 = _nodeBasedGraph->GetEdgeData(edge1);
|
||||
_NodeBasedDynamicGraph::EdgeData data2 = _nodeBasedGraph->GetEdgeData(edge2);
|
||||
|
||||
if(data1.middleName.nameID == data2.middleName.nameID) {
|
||||
return TurnInstructions.NoTurn;
|
||||
}
|
||||
return TurnInstructions.GoStraight;
|
||||
}
|
||||
|
||||
unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const {
|
||||
return edgeBasedEdges.size();
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "../DataStructures/ExtractorStructs.h"
|
||||
#include "../DataStructures/ImportEdge.h"
|
||||
#include "../DataStructures/Percent.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
|
||||
class EdgeBasedGraphFactory {
|
||||
private:
|
||||
@ -56,7 +57,6 @@ private:
|
||||
int distance;
|
||||
unsigned via;
|
||||
unsigned nameID;
|
||||
// unsigned nameID2;
|
||||
bool forward;
|
||||
bool backward;
|
||||
short turnInstruction;
|
||||
@ -103,7 +103,7 @@ public:
|
||||
template< class ImportEdgeT >
|
||||
void GetEdgeBasedEdges( std::vector< ImportEdgeT >& edges );
|
||||
void GetEdgeBasedNodes( std::vector< EdgeBasedNode> & nodes);
|
||||
|
||||
short AnalyzeTurn(const NodeID u, const NodeID v, const NodeID w) const;
|
||||
unsigned GetNumberOfNodes() const;
|
||||
};
|
||||
|
||||
|
112
DataStructures/DescriptionFactory.cpp
Normal file
112
DataStructures/DescriptionFactory.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
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() {
|
||||
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
DataStructures/DescriptionFactory.h
Normal file
176
DataStructures/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 "ExtractorStructs.h"
|
||||
#include "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_ */
|
@ -24,7 +24,9 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "BaseDescriptor.h"
|
||||
#include "../DataStructures/JSONDescriptionFactory.h"
|
||||
#include "../DataStructures/DescriptionFactory.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
template<class SearchEngineT>
|
||||
@ -32,7 +34,7 @@ class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||
private:
|
||||
_DescriptorConfig config;
|
||||
_RouteSummary summary;
|
||||
JSONDescriptionFactory descriptionFactory;
|
||||
DescriptionFactory descriptionFactory;
|
||||
std::string tmp;
|
||||
_Coordinate current;
|
||||
|
||||
@ -44,33 +46,29 @@ public:
|
||||
WriteHeaderToOutput(reply.content);
|
||||
//We do not need to do much, if there is no route ;-)
|
||||
|
||||
//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);
|
||||
descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
|
||||
summary.destName = sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID);
|
||||
summary.BuildDurationAndLengthStrings(0, durationOfTrip);
|
||||
reply.content += "0,"
|
||||
"\"status_message\": \"Found route between points\",";
|
||||
descriptionFactory.AddToPolyline(phantomNodes.startPhantom.location);
|
||||
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
|
||||
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
|
||||
BOOST_FOREACH(_PathData pathData, path) {
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
descriptionFactory.AppendSegment(pathData, current);
|
||||
if(pathData.turnInstruction != 0) {
|
||||
INFO("Turn on " << sEngine.GetEscapedNameForNameID(pathData.nameID) << ", turnID: " << pathData.turnInstruction );
|
||||
}
|
||||
descriptionFactory.AppendSegment(current, pathData );
|
||||
}
|
||||
//TODO: Add via points
|
||||
}
|
||||
descriptionFactory.AddToPolyline(phantomNodes.targetPhantom.location);
|
||||
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;
|
||||
@ -88,17 +86,46 @@ public:
|
||||
reply.content += "\"route_geometry\": ";
|
||||
if(config.geometry) {
|
||||
if(config.encodeGeometry)
|
||||
descriptionFactory.AppendEncodedPolylineString(reply.content);
|
||||
else
|
||||
descriptionFactory.AppendUnencodedPolylineString(reply.content);
|
||||
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
|
||||
} else {
|
||||
reply.content += "[]";
|
||||
}
|
||||
|
||||
reply.content += ","
|
||||
"\"route_instructions\": [";
|
||||
if(config.instructions)
|
||||
descriptionFactory.AppendRouteInstructionString(reply.content);
|
||||
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\":[";
|
||||
|
@ -171,8 +171,6 @@ public:
|
||||
rawRoute.routeSegments[i] = path;
|
||||
}
|
||||
}
|
||||
INFO("Found path of length " << distance);
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
BaseDescriptor<SearchEngine<EdgeData, StaticGraph<EdgeData> > > * desc;
|
||||
|
Loading…
Reference in New Issue
Block a user