Add first nodes with negative weights
This commit is contained in:
+3
-121
@@ -30,7 +30,6 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include "../typedefs.h"
|
||||
#include "../DataStructures/ExtractorStructs.h"
|
||||
#include "../DataStructures/HashTable.h"
|
||||
#include "../DataStructures/PolylineCompressor.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include "RawRouteData.h"
|
||||
@@ -51,65 +50,30 @@ static double GetAngleBetweenTwoEdges(const _Coordinate& A, const _Coordinate& C
|
||||
return angle;
|
||||
}
|
||||
|
||||
struct RouteSummary {
|
||||
struct _RouteSummary {
|
||||
std::string lengthString;
|
||||
std::string durationString;
|
||||
std::string startName;
|
||||
std::string destName;
|
||||
RouteSummary() : lengthString("0"), durationString("0"), startName("unknown street"), destName("unknown street") {}
|
||||
_RouteSummary() : lengthString("0"), durationString("0"), startName("unknown street"), destName("unknown street") {}
|
||||
void BuildDurationAndLengthStrings(double distance, unsigned time) {
|
||||
//compute distance/duration for route summary
|
||||
std::ostringstream s;
|
||||
s << 10*(round(distance/10.));
|
||||
lengthString = s.str();
|
||||
int travelTime = 60*(time/60.) + 1;
|
||||
int travelTime = time/10 + 1;
|
||||
s.str("");
|
||||
s << travelTime;
|
||||
durationString = s.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct DirectionOfInstruction {
|
||||
std::string direction;
|
||||
std::string shortDirection;
|
||||
};
|
||||
|
||||
struct DescriptorState {
|
||||
_Coordinate currentCoordinate, nextCoordinate, previousCoordinate, tmpCoord, startOfSegmentCoordinate;
|
||||
std::string routeGeometryString;
|
||||
std::string routeInstructionString;
|
||||
unsigned lastNameID, currentNameID, geometryCounter, startIndexOfGeometry;
|
||||
double entireDistance, distanceOfInstruction, durationOfInstruction;
|
||||
|
||||
DescriptorState() : lastNameID(0), currentNameID(0), geometryCounter(0), startIndexOfGeometry(0), entireDistance(0.), distanceOfInstruction(0.), durationOfInstruction(0.) {};
|
||||
double GetAngleBetweenCoordinates() const {
|
||||
return GetAngleBetweenTwoEdges(previousCoordinate, currentCoordinate, nextCoordinate);
|
||||
}
|
||||
bool CurrentAndPreviousNameIDsEqual() const {
|
||||
return lastNameID == currentNameID;
|
||||
}
|
||||
void SetStartOfSegment() {
|
||||
startOfSegmentCoordinate = nextCoordinate;
|
||||
entireDistance += distanceOfInstruction;
|
||||
lastNameID = currentNameID;
|
||||
distanceOfInstruction = 0;
|
||||
startIndexOfGeometry = geometryCounter-1;
|
||||
}
|
||||
void PrintCoordinates() {
|
||||
#ifdef DEBUG
|
||||
std::cout << "prev: " << previousCoordinate << ", curr: " << currentCoordinate << ", next: " << nextCoordinate << std::endl;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
struct _DescriptorConfig {
|
||||
_DescriptorConfig() : instructions(true), geometry(true), encodeGeometry(false), z(18) {}
|
||||
bool instructions;
|
||||
bool geometry;
|
||||
bool encodeGeometry;
|
||||
unsigned short z;
|
||||
|
||||
PolylineCompressor pc;
|
||||
};
|
||||
|
||||
template<class SearchEngineT>
|
||||
@@ -122,86 +86,4 @@ public:
|
||||
virtual void SetConfig(const _DescriptorConfig & config) = 0;
|
||||
};
|
||||
|
||||
static inline void getDirectionOfInstruction(double angle, DirectionOfInstruction & dirInst) {
|
||||
if(angle >= 23 && angle < 67) {
|
||||
dirInst.direction = "southeast";
|
||||
dirInst.shortDirection = "SE";
|
||||
return;
|
||||
}
|
||||
if(angle >= 67 && angle < 113) {
|
||||
dirInst.direction = "south";
|
||||
dirInst.shortDirection = "S";
|
||||
return;
|
||||
}
|
||||
if(angle >= 113 && angle < 158) {
|
||||
dirInst.direction = "southwest";
|
||||
dirInst.shortDirection = "SW";
|
||||
return;
|
||||
}
|
||||
if(angle >= 158 && angle < 202) {
|
||||
dirInst.direction = "west";
|
||||
dirInst.shortDirection = "W";
|
||||
return;
|
||||
}
|
||||
if(angle >= 202 && angle < 248) {
|
||||
dirInst.direction = "northwest";
|
||||
dirInst.shortDirection = "NW";
|
||||
return;
|
||||
}
|
||||
if(angle >= 248 && angle < 292) {
|
||||
dirInst.direction = "north";
|
||||
dirInst.shortDirection = "N";
|
||||
return;
|
||||
}
|
||||
if(angle >= 292 && angle < 336) {
|
||||
dirInst.direction = "northeast";
|
||||
dirInst.shortDirection = "NE";
|
||||
return;
|
||||
}
|
||||
dirInst.direction = "East";
|
||||
dirInst.shortDirection = "E";
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void getTurnDirectionOfInstruction(double angle, std::string & output) {
|
||||
if(angle >= 23 && angle < 67) {
|
||||
output = "Turn sharp right";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
if (angle >= 67 && angle < 113) {
|
||||
output = "Turn right";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
if (angle >= 113 && angle < 158) {
|
||||
output = "Bear right";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (angle >= 158 && angle < 202) {
|
||||
output = "Continue";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
if (angle >= 202 && angle < 248) {
|
||||
output = "Bear left";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
if (angle >= 248 && angle < 292) {
|
||||
output = "Turn left";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
if (angle >= 292 && angle < 336) {
|
||||
output = "Turn sharp left";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
return;
|
||||
}
|
||||
output = "U-Turn";
|
||||
// cout << "angle " << angle << "-> " << output << endl;
|
||||
}
|
||||
|
||||
#endif /* BASE_DESCRIPTOR_H_ */
|
||||
|
||||
+22
-63
@@ -24,44 +24,47 @@ or see http://www.gnu.org/licenses/agpl.txt.
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "BaseDescriptor.h"
|
||||
#include "../DataStructures/PolylineCompressor.h"
|
||||
#include "../DataStructures/JSONDescriptionFactory.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
template<class SearchEngineT>
|
||||
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
|
||||
private:
|
||||
_DescriptorConfig config;
|
||||
RouteSummary summary;
|
||||
DirectionOfInstruction directionOfInstruction;
|
||||
DescriptorState descriptorState;
|
||||
_RouteSummary summary;
|
||||
JSONDescriptionFactory descriptionFactory;
|
||||
std::string tmp;
|
||||
vector<_Coordinate> polyline;
|
||||
_Coordinate current;
|
||||
|
||||
public:
|
||||
JSONDescriptor() {}
|
||||
void SetConfig(const _DescriptorConfig & c) { config = c; }
|
||||
|
||||
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned distance) {
|
||||
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned durationOfTrip) {
|
||||
WriteHeaderToOutput(reply.content);
|
||||
//We do not need to do much, if there is no route ;-)
|
||||
|
||||
if(distance != UINT_MAX && rawRoute.routeSegments.size() > 0) {
|
||||
//INFO("Starting at " << sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID) << ", id: " << phantomNodes.startPhantom.nodeBasedEdgeNameID);
|
||||
//INFO("Arriving at " << sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID) << ", id: " << phantomNodes.startPhantom.nodeBasedEdgeNameID);
|
||||
|
||||
if(durationOfTrip != INT_MAX && rawRoute.routeSegments.size() > 0) {
|
||||
summary.startName = sEngine.GetEscapedNameForNameID(phantomNodes.startPhantom.nodeBasedEdgeNameID);
|
||||
summary.destName = sEngine.GetEscapedNameForNameID(phantomNodes.targetPhantom.nodeBasedEdgeNameID);
|
||||
summary.BuildDurationAndLengthStrings(0, durationOfTrip);
|
||||
reply.content += "0,"
|
||||
"\"status_message\": \"Found route between points\",";
|
||||
|
||||
//Put first segment of route into geometry
|
||||
polyline.push_back(phantomNodes.startPhantom.location);
|
||||
|
||||
descriptionFactory.AddToPolyline(phantomNodes.startPhantom.location);
|
||||
for(unsigned segmentIdx = 0; segmentIdx < rawRoute.routeSegments.size(); segmentIdx++) {
|
||||
const std::vector< _PathData > & path = rawRoute.routeSegments[segmentIdx];
|
||||
BOOST_FOREACH(_PathData pathData, path) {
|
||||
_Coordinate current;
|
||||
sEngine.GetCoordinatesForNodeID(pathData.node, current);
|
||||
polyline.push_back(current);
|
||||
// INFO(pathData.node << " at " << current.lat << "," << current.lon);
|
||||
//INFO("routed over node: " << pathData.node);
|
||||
descriptionFactory.AppendSegment(pathData, current);
|
||||
if(pathData.turnInstruction != 0) {
|
||||
INFO("Turn on " << sEngine.GetEscapedNameForNameID(pathData.nameID) << ", turnID: " << pathData.turnInstruction );
|
||||
}
|
||||
}
|
||||
}
|
||||
polyline.push_back(phantomNodes.targetPhantom.location);
|
||||
descriptionFactory.AddToPolyline(phantomNodes.targetPhantom.location);
|
||||
} else {
|
||||
//no route found
|
||||
reply.content += "207,"
|
||||
@@ -85,11 +88,9 @@ public:
|
||||
reply.content += "\"route_geometry\": ";
|
||||
if(config.geometry) {
|
||||
if(config.encodeGeometry)
|
||||
config.pc.printEncodedString(polyline, descriptorState.routeGeometryString);
|
||||
descriptionFactory.AppendEncodedPolylineString(reply.content);
|
||||
else
|
||||
config.pc.printUnencodedString(polyline, descriptorState.routeGeometryString);
|
||||
|
||||
reply.content += descriptorState.routeGeometryString;
|
||||
descriptionFactory.AppendUnencodedPolylineString(reply.content);
|
||||
} else {
|
||||
reply.content += "[]";
|
||||
}
|
||||
@@ -97,7 +98,7 @@ public:
|
||||
reply.content += ","
|
||||
"\"route_instructions\": [";
|
||||
if(config.instructions)
|
||||
reply.content += descriptorState.routeInstructionString;
|
||||
descriptionFactory.AppendRouteInstructionString(reply.content);
|
||||
reply.content += "],";
|
||||
//list all viapoints so that the client may display it
|
||||
reply.content += "\"via_points\":[";
|
||||
@@ -116,48 +117,6 @@ public:
|
||||
"\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.2)\"";
|
||||
reply.content += "}";
|
||||
}
|
||||
private:
|
||||
void appendInstructionNameToString(const std::string & nameOfStreet, const std::string & instructionOrDirection, std::string &output, bool firstAdvice = false) {
|
||||
output += "[";
|
||||
if(config.instructions) {
|
||||
output += "\"";
|
||||
if(firstAdvice) {
|
||||
output += "Head ";
|
||||
}
|
||||
output += instructionOrDirection;
|
||||
output += "\",\"";
|
||||
output += nameOfStreet;
|
||||
output += "\",";
|
||||
}
|
||||
}
|
||||
|
||||
void appendInstructionLengthToString(unsigned length, std::string &output) {
|
||||
if(config.instructions){
|
||||
std::string tmpDistance;
|
||||
intToString(10*(round(length/10.)), tmpDistance);
|
||||
output += tmpDistance;
|
||||
output += ",";
|
||||
intToString(descriptorState.startIndexOfGeometry, tmp);
|
||||
output += tmp;
|
||||
output += ",";
|
||||
intToString(descriptorState.durationOfInstruction, tmp);
|
||||
output += tmp;
|
||||
output += ",";
|
||||
output += "\"";
|
||||
output += tmpDistance;
|
||||
output += "\",";
|
||||
double angle = descriptorState.GetAngleBetweenCoordinates();
|
||||
DirectionOfInstruction direction;
|
||||
getDirectionOfInstruction(angle, direction);
|
||||
output += "\"";
|
||||
output += direction.shortDirection;
|
||||
output += "\",";
|
||||
std::stringstream numberString;
|
||||
numberString << fixed << setprecision(2) << angle;
|
||||
output += numberString.str();
|
||||
}
|
||||
output += "]";
|
||||
}
|
||||
|
||||
void WriteHeaderToOutput(std::string & output) {
|
||||
output += "{"
|
||||
|
||||
+50
-33
@@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
|
||||
virtual ~ViaRoutePlugin() {
|
||||
DELETE( searchEngine );
|
||||
DELETE( searchEngine );
|
||||
}
|
||||
|
||||
std::string GetDescriptor() { return pluginDescriptorString; }
|
||||
@@ -101,7 +101,6 @@ public:
|
||||
}
|
||||
rawRoute.rawViaNodeCoordinates.push_back(startCoord);
|
||||
|
||||
INFO("[debug] number of vianodes: " << routeParameters.viaPoints.size());
|
||||
for(unsigned i = 0; i < routeParameters.viaPoints.size(); i++) {
|
||||
textCoord = split (routeParameters.viaPoints[i], ',');
|
||||
if(textCoord.size() != 2) {
|
||||
@@ -123,7 +122,7 @@ public:
|
||||
bool errorOccurredFlag = false;
|
||||
|
||||
for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); i++) {
|
||||
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i]);
|
||||
searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i]);
|
||||
if(!rawRoute.rawViaNodeCoordinates[i].isSet()) {
|
||||
errorOccurredFlag = true;
|
||||
}
|
||||
@@ -132,29 +131,47 @@ public:
|
||||
rawRoute.Resize();
|
||||
unsigned distance = 0;
|
||||
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1 && !errorOccurredFlag; i++) {
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||
INFO(segmentPhantomNodes);
|
||||
std::vector< _PathData > path;
|
||||
unsigned distanceOfSegment = searchEngine->ComputeRoute(segmentPhantomNodes, path);
|
||||
|
||||
if(UINT_MAX == distanceOfSegment ) {
|
||||
errorOccurredFlag = true;
|
||||
INFO( "Error occurred, path not found" );
|
||||
distance = UINT_MAX;
|
||||
break;
|
||||
} else {
|
||||
distance += distanceOfSegment;
|
||||
//single route or via point routing
|
||||
if(0 == routeParameters.viaPoints.size()) {
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[0];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[1];
|
||||
std::vector< _PathData > path;
|
||||
distance = searchEngine->ComputeRoute(segmentPhantomNodes, path);
|
||||
|
||||
if(UINT_MAX == distance ) {
|
||||
INFO( "Error occurred, single path not found" );
|
||||
}
|
||||
|
||||
//put segments at correct position of routes raw data
|
||||
rawRoute.segmentEndCoordinates[i] = (segmentPhantomNodes);
|
||||
rawRoute.routeSegments[i] = path;
|
||||
}
|
||||
rawRoute.segmentEndCoordinates[0] = (segmentPhantomNodes);
|
||||
rawRoute.routeSegments[0] = path;
|
||||
} else {
|
||||
//Getting the shortest via path is a dynamic programming problem and is solved as such.
|
||||
for(unsigned i = 0; i < phantomNodeVector.size()-1 && !errorOccurredFlag; i++) {
|
||||
PhantomNodes segmentPhantomNodes;
|
||||
segmentPhantomNodes.startPhantom = phantomNodeVector[i];
|
||||
segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1];
|
||||
INFO(segmentPhantomNodes);
|
||||
std::vector< _PathData > path;
|
||||
unsigned distanceOfSegment = searchEngine->ComputeRoute(segmentPhantomNodes, path);
|
||||
|
||||
INFO("Found path of length: " << distance);
|
||||
if(UINT_MAX == distanceOfSegment ) {
|
||||
errorOccurredFlag = true;
|
||||
INFO( "Error occurred, via path not found" );
|
||||
distance = UINT_MAX;
|
||||
break;
|
||||
} else {
|
||||
distance += distanceOfSegment;
|
||||
}
|
||||
|
||||
//put segments at correct position of routes raw data
|
||||
rawRoute.segmentEndCoordinates[i] = (segmentPhantomNodes);
|
||||
rawRoute.routeSegments[i] = path;
|
||||
}
|
||||
}
|
||||
INFO("Found path of length " << distance);
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
@@ -215,13 +232,6 @@ public:
|
||||
reply.headers[0].value = tmp;
|
||||
switch(descriptorType){
|
||||
case 0:
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.kml\"";
|
||||
|
||||
break;
|
||||
case 1:
|
||||
if("" != JSONParameter){
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
@@ -235,7 +245,7 @@ public:
|
||||
}
|
||||
|
||||
break;
|
||||
case 2:
|
||||
case 1:
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
@@ -243,10 +253,17 @@ public:
|
||||
|
||||
break;
|
||||
default:
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/vnd.google-earth.kml+xml; charset=UTF-8";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.kml\"";
|
||||
if("" != JSONParameter){
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
||||
} else {
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user