Fixes issue 63

This commit is contained in:
DennisOSRM 2011-12-17 13:44:01 +01:00
parent f5226b2228
commit b133beed5e

View File

@ -32,145 +32,146 @@ or see http://www.gnu.org/licenses/agpl.txt.
template<class SearchEngineT>
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
private:
_DescriptorConfig config;
_RouteSummary summary;
DescriptionFactory descriptionFactory;
std::string tmp;
_Coordinate current;
struct {
int startIndex;
int nameID;
int leaveAtExit;
} roundAbout;
_DescriptorConfig config;
_RouteSummary summary;
DescriptionFactory descriptionFactory;
_Coordinate current;
struct {
int startIndex;
int nameID;
int leaveAtExit;
} roundAbout;
public:
JSONDescriptor() {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
JSONDescriptor() {}
void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, unsigned durationOfTrip) {
WriteHeaderToOutput(reply.content);
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 {
//We do not need to do much, if there is no route ;-)
reply.content += "207,"
"\"status_message\": \"Cannot find route between points\",";
}
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, const unsigned durationOfTrip) {
WriteHeaderToOutput(reply.content);
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) {
BOOST_FOREACH(_PathData & pathData, rawRoute.routeSegments[segmentIdx]) {
sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData );
}
}
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
} else {
//We do not need to do much, if there is no route ;-)
reply.content += "207,"
"\"status_message\": \"Cannot find route between points\",";
}
summary.BuildDurationAndLengthStrings(descriptionFactory.Run(config.z), durationOfTrip);
summary.BuildDurationAndLengthStrings(descriptionFactory.Run(config.z), 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_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) {
//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
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0;
std::string tmpDist, tmpLength, tmp;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(SegmentInformation segment, descriptionFactory.pathDescription) {
if(TurnInstructions.TurnIsNecessary( segment.turnInstruction) ) {
if(TurnInstructions.EnterRoundAbout == segment.turnInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments)
reply.content += ",";
reply.content += ","
"\"route_instructions\": [";
if(config.instructions) {
//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
unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0;
std::string tmpDist, tmpLength, tmpDuration;
//Fetch data from Factory and generate a string from it.
BOOST_FOREACH(SegmentInformation & segment, descriptionFactory.pathDescription) {
if(TurnInstructions.TurnIsNecessary( segment.turnInstruction) ) {
if(TurnInstructions.EnterRoundAbout == segment.turnInstruction) {
roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments;
} else {
if(0 != prefixSumOfNecessarySegments)
reply.content += ",";
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == segment.turnInstruction) {
reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout];
reply.content += " and leave at ";
reply.content += TurnInstructions.Ordinals[roundAbout.leaveAtExit+1];
reply.content += " exit";
roundAbout.leaveAtExit = 0;
} else {
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 += "]";
}
} else if(TurnInstructions.StayOnRoundAbout == segment.turnInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
}
}
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 += "}";
}
reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == segment.turnInstruction) {
reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout];
reply.content += " and leave at ";
reply.content += TurnInstructions.Ordinals[roundAbout.leaveAtExit+1];
reply.content += " exit";
roundAbout.leaveAtExit = 0;
} else {
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, tmpDuration);
reply.content += tmpDuration;
reply.content += ",\"";
reply.content += tmpLength;
//TODO: fix heading
reply.content += "\",\"NE\",22.5";
reply.content += "]";
}
} else if(TurnInstructions.StayOnRoundAbout == segment.turnInstruction) {
++roundAbout.leaveAtExit;
}
if(segment.necessary)
++prefixSumOfNecessarySegments;
}
}
reply.content += "],";
//list all viapoints so that the client may display it
reply.content += "\"via_points\":[";
if(true == config.geometry) {
std::string tmp;
for(unsigned segmentIdx = 1; 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.3)\"";
reply.content += "}";
}
void WriteHeaderToOutput(std::string & output) {
output += "{"
"\"version\": 0.3,"
"\"status\":";
}
inline void WriteHeaderToOutput(std::string & output) {
output += "{"
"\"version\": 0.3,"
"\"status\":";
}
};
#endif /* JSON_DESCRIPTOR_H_ */