Fixes issue #202

This commit is contained in:
DennisOSRM 2012-03-23 17:44:56 +01:00
parent 2549f7254a
commit e4080aba05

View File

@ -34,167 +34,168 @@ or see http://www.gnu.org/licenses/agpl.txt.
template<class SearchEngineT> template<class SearchEngineT>
class JSONDescriptor : public BaseDescriptor<SearchEngineT>{ class JSONDescriptor : public BaseDescriptor<SearchEngineT>{
private: private:
_DescriptorConfig config; _DescriptorConfig config;
DescriptionFactory descriptionFactory; DescriptionFactory descriptionFactory;
_Coordinate current; _Coordinate current;
unsigned numberOfEnteredRestrictedAreas; unsigned numberOfEnteredRestrictedAreas;
struct { struct {
int startIndex; int startIndex;
int nameID; int nameID;
int leaveAtExit; int leaveAtExit;
} roundAbout; } roundAbout;
public: public:
JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {} JSONDescriptor() : numberOfEnteredRestrictedAreas(0) {}
void SetConfig(const _DescriptorConfig & c) { config = c; } void SetConfig(const _DescriptorConfig & c) { config = c; }
void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, const unsigned durationOfTrip) { void Run(http::Reply & reply, RawRouteData &rawRoute, PhantomNodes &phantomNodes, SearchEngineT &sEngine, const unsigned durationOfTrip) {
WriteHeaderToOutput(reply.content); WriteHeaderToOutput(reply.content);
if(durationOfTrip != INT_MAX) { if(durationOfTrip != INT_MAX) {
descriptionFactory.SetStartSegment(phantomNodes.startPhantom); descriptionFactory.SetStartSegment(phantomNodes.startPhantom);
reply.content += "0," reply.content += "0,"
"\"status_message\": \"Found route between points\","; "\"status_message\": \"Found route between points\",";
//Get all the coordinates for the computed route //Get all the coordinates for the computed route
BOOST_FOREACH(_PathData & pathData, rawRoute.computedRouted) { BOOST_FOREACH(_PathData & pathData, rawRoute.computedRouted) {
sEngine.GetCoordinatesForNodeID(pathData.node, current); sEngine.GetCoordinatesForNodeID(pathData.node, current);
descriptionFactory.AppendSegment(current, pathData ); descriptionFactory.AppendSegment(current, pathData );
} }
descriptionFactory.SetEndSegment(phantomNodes.targetPhantom); descriptionFactory.SetEndSegment(phantomNodes.targetPhantom);
} else { } else {
//We do not need to do much, if there is no route ;-) //We do not need to do much, if there is no route ;-)
reply.content += "207," reply.content += "207,"
"\"status_message\": \"Cannot find route between points\","; "\"status_message\": \"Cannot find route between points\",";
} }
descriptionFactory.Run(sEngine, config.z, durationOfTrip); descriptionFactory.Run(sEngine, config.z, durationOfTrip);
reply.content += "\"route_geometry\": "; reply.content += "\"route_geometry\": ";
if(config.geometry) { if(config.geometry) {
descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry); descriptionFactory.AppendEncodedPolylineString(reply.content, config.encodeGeometry);
} else { } else {
reply.content += "[]"; reply.content += "[]";
} }
reply.content += "," reply.content += ","
"\"route_instructions\": ["; "\"route_instructions\": [";
if(config.instructions) { if(config.instructions) {
//Segment information has following format: //Segment information has following format:
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth] //["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
//Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5] //Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
//See also: http://developers.cloudmade.com/wiki/navengine/JSON_format //See also: http://developers.cloudmade.com/wiki/navengine/JSON_format
unsigned prefixSumOfNecessarySegments = 0; unsigned prefixSumOfNecessarySegments = 0;
roundAbout.leaveAtExit = 0; roundAbout.leaveAtExit = 0;
roundAbout.nameID = 0; roundAbout.nameID = 0;
std::string tmpDist, tmpLength, tmpDuration, tmpBearing; std::string tmpDist, tmpLength, tmpDuration, tmpBearing;
//Fetch data from Factory and generate a string from it. //Fetch data from Factory and generate a string from it.
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) { BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction); numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
if(TurnInstructions.TurnIsNecessary( currentInstruction) ) { if(TurnInstructions.TurnIsNecessary( currentInstruction) ) {
if(TurnInstructions.EnterRoundAbout == currentInstruction) { if(TurnInstructions.EnterRoundAbout == currentInstruction) {
roundAbout.nameID = segment.nameID; roundAbout.nameID = segment.nameID;
roundAbout.startIndex = prefixSumOfNecessarySegments; roundAbout.startIndex = prefixSumOfNecessarySegments;
} else { } else {
if(0 != prefixSumOfNecessarySegments){ if(0 != prefixSumOfNecessarySegments){
reply.content += ","; reply.content += ",";
} }
reply.content += "[\""; reply.content += "[\"";
if(TurnInstructions.LeaveRoundAbout == currentInstruction) { if(TurnInstructions.LeaveRoundAbout == currentInstruction) {
reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout]; reply.content += TurnInstructions.TurnStrings[TurnInstructions.EnterRoundAbout];
reply.content += " and leave at "; reply.content += " and leave at ";
reply.content += TurnInstructions.Ordinals[std::min(11,roundAbout.leaveAtExit+1)]; reply.content += TurnInstructions.Ordinals[std::min(11,roundAbout.leaveAtExit+1)];
reply.content += " exit"; reply.content += " exit";
roundAbout.leaveAtExit = 0; roundAbout.leaveAtExit = 0;
} else { } else {
reply.content += TurnInstructions.TurnStrings[currentInstruction]; reply.content += TurnInstructions.TurnStrings[currentInstruction];
} }
reply.content += "\",\""; reply.content += "\",\"";
reply.content += sEngine.GetEscapedNameForNameID(segment.nameID); reply.content += sEngine.GetEscapedNameForNameID(segment.nameID);
reply.content += "\","; reply.content += "\",";
intToString(segment.length, tmpDist); intToString(segment.length, tmpDist);
reply.content += tmpDist; reply.content += tmpDist;
reply.content += ","; reply.content += ",";
intToString(prefixSumOfNecessarySegments, tmpLength); intToString(prefixSumOfNecessarySegments, tmpLength);
reply.content += tmpLength; reply.content += tmpLength;
reply.content += ","; reply.content += ",";
intToString(segment.duration, tmpDuration); intToString(segment.duration, tmpDuration);
reply.content += tmpDuration; reply.content += tmpDuration;
reply.content += ",\""; reply.content += ",\"";
intToString(segment.length, tmpLength); intToString(segment.length, tmpLength);
reply.content += tmpLength; reply.content += tmpLength;
reply.content += "m\",\""; reply.content += "m\",\"";
reply.content += Azimuth::Get(segment.bearing); reply.content += Azimuth::Get(segment.bearing);
reply.content += "\","; reply.content += "\",";
doubleToStringWithTwoDigitsBehindComma(segment.bearing, tmpBearing); doubleToStringWithTwoDigitsBehindComma(segment.bearing, tmpBearing);
reply.content += tmpBearing; reply.content += tmpBearing;
reply.content += "]"; reply.content += "]";
} }
} else if(TurnInstructions.StayOnRoundAbout == currentInstruction) { } else if(TurnInstructions.StayOnRoundAbout == currentInstruction) {
++roundAbout.leaveAtExit; ++roundAbout.leaveAtExit;
} }
if(segment.necessary) if(segment.necessary)
++prefixSumOfNecessarySegments; ++prefixSumOfNecessarySegments;
} }
if(durationOfTrip != INT_MAX) {
reply.content += ",[\""; reply.content += ",[\"";
reply.content += TurnInstructions.TurnStrings[TurnInstructions.ReachedYourDestination]; reply.content += TurnInstructions.TurnStrings[TurnInstructions.ReachedYourDestination];
reply.content += "\",\""; reply.content += "\",\"";
reply.content += "\","; reply.content += "\",";
reply.content += "0"; reply.content += "0";
reply.content += ","; reply.content += ",";
intToString(prefixSumOfNecessarySegments-1, tmpLength); intToString(prefixSumOfNecessarySegments-1, tmpLength);
reply.content += tmpLength; reply.content += tmpLength;
reply.content += ","; reply.content += ",";
reply.content += "0"; reply.content += "0";
reply.content += ",\""; reply.content += ",\"";
reply.content += "\",\""; reply.content += "\",\"";
reply.content += Azimuth::Get(0.0); reply.content += Azimuth::Get(0.0);
reply.content += "\","; reply.content += "\",";
reply.content += "0.0"; reply.content += "0.0";
reply.content += "]"; reply.content += "]";
} else { }
} else {
BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) { BOOST_FOREACH(const SegmentInformation & segment, descriptionFactory.pathDescription) {
short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag; short currentInstruction = segment.turnInstruction & TurnInstructions.InverseAccessRestrictionFlag;
numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction); numberOfEnteredRestrictedAreas += (currentInstruction != segment.turnInstruction);
} }
} }
reply.content += "],"; reply.content += "],";
// INFO("Entered " << numberOfEnteredRestrictedAreas << " restricted areas"); // INFO("Entered " << numberOfEnteredRestrictedAreas << " restricted areas");
descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, durationOfTrip - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenaly)); descriptionFactory.BuildRouteSummary(descriptionFactory.entireLength, durationOfTrip - ( numberOfEnteredRestrictedAreas*TurnInstructions.AccessRestrictionPenaly));
reply.content += "\"route_summary\": {" reply.content += "\"route_summary\": {"
"\"total_distance\":"; "\"total_distance\":";
reply.content += descriptionFactory.summary.lengthString; reply.content += descriptionFactory.summary.lengthString;
reply.content += "," reply.content += ","
"\"total_time\":"; "\"total_time\":";
reply.content += descriptionFactory.summary.durationString; reply.content += descriptionFactory.summary.durationString;
reply.content += "," reply.content += ","
"\"start_point\":\""; "\"start_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName); reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.startName);
reply.content += "\"," reply.content += "\","
"\"end_point\":\""; "\"end_point\":\"";
reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName); reply.content += sEngine.GetEscapedNameForNameID(descriptionFactory.summary.destName);
reply.content += "\""; reply.content += "\"";
reply.content += "},"; reply.content += "},";
//list all viapoints so that the client may display it //list all viapoints so that the client may display it
reply.content += "\"via_points\":["; reply.content += "\"via_points\":[";
std::string tmp; std::string tmp;
if(true == config.geometry) { if(true == config.geometry) {
for(unsigned segmentIdx = 1; segmentIdx < rawRoute.segmentEndCoordinates.size(); ++segmentIdx) { for(unsigned segmentIdx = 1; segmentIdx < rawRoute.segmentEndCoordinates.size(); ++segmentIdx) {
if(segmentIdx > 1) if(segmentIdx > 1)
reply.content += ","; reply.content += ",";
reply.content += "["; reply.content += "[";
if(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location.isSet()) if(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location.isSet())
convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, tmp); convertInternalReversedCoordinateToString(rawRoute.segmentEndCoordinates[segmentIdx].startPhantom.location, tmp);
else else
convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[segmentIdx], tmp); convertInternalReversedCoordinateToString(rawRoute.rawViaNodeCoordinates[segmentIdx], tmp);
reply.content += tmp; reply.content += tmp;
reply.content += "]"; reply.content += "]";
} }
} }
reply.content += "],"; reply.content += "],";
reply.content += "\"hint_data\": {"; reply.content += "\"hint_data\": {";
reply.content += "\"checksum\":"; reply.content += "\"checksum\":";
intToString(rawRoute.checkSum, tmp); intToString(rawRoute.checkSum, tmp);
@ -214,14 +215,14 @@ public:
reply.content += hint; reply.content += hint;
reply.content += "\"]"; reply.content += "\"]";
reply.content += "},"; reply.content += "},";
reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\""; reply.content += "\"transactionId\": \"OSRM Routing Engine JSON Descriptor (v0.3)\"";
reply.content += "}"; reply.content += "}";
} }
inline void WriteHeaderToOutput(std::string & output) { inline void WriteHeaderToOutput(std::string & output) {
output += "{" output += "{"
"\"version\": 0.3," "\"version\": 0.3,"
"\"status\":"; "\"status\":";
} }
}; };
#endif /* JSON_DESCRIPTOR_H_ */ #endif /* JSON_DESCRIPTOR_H_ */