implements output generation through a dedicated JSON container:

- JSON syntax is not scattered over several files, but one place
- Reduces code duplication
- breaking changes:
  - new property in json(p) formatted response: "found_alternative": True/False
  - returned filenames now response.js(on) or route.gpx
  - /hello plugin returns JSON now
This commit is contained in:
Dennis Luxen
2014-05-16 16:09:40 +02:00
parent acab77f4f8
commit a80815d57a
28 changed files with 1092 additions and 675 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ struct DescriptorConfig
template <class DataFacadeT> class BaseDescriptor
{
public:
BaseDescriptor() {}
BaseDescriptor() {} //TODO: initialize facade here.
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() {}
virtual void Run(const RawRouteData &raw_route,
+7 -22
View File
@@ -94,38 +94,23 @@ void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
}
}
void DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded,
std::vector<std::string> &output)
JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
{
std::string temp;
if (return_encoded)
{
polyline_compressor.printEncodedString(path_description, temp);
return polyline_compressor.printEncodedString(path_description);
}
else
{
polyline_compressor.printUnencodedString(path_description, temp);
}
output.emplace_back(temp);
return polyline_compressor.printUnencodedString(path_description);
}
void DescriptionFactory::AppendEncodedPolylineString(std::vector<std::string> &output) const
JSON::Value DescriptionFactory::AppendUnencodedPolylineString() const
{
std::string temp;
polyline_compressor.printEncodedString(path_description, temp);
output.emplace_back(temp);
}
void DescriptionFactory::AppendUnencodedPolylineString(std::vector<std::string> &output) const
{
std::string temp;
polyline_compressor.printUnencodedString(path_description, temp);
output.emplace_back(temp);
return polyline_compressor.printUnencodedString(path_description);
}
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
{
summary.startName = start_phantom.name_id;
summary.destName = target_phantom.name_id;
summary.source_name_id = start_phantom.name_id;
summary.target_name_id = target_phantom.name_id;
summary.BuildDurationAndLengthStrings(distance, time);
}
+11 -13
View File
@@ -57,18 +57,17 @@ class DescriptionFactory
public:
struct RouteSummary
{
std::string lengthString;
std::string durationString;
unsigned startName;
unsigned destName;
RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
unsigned distance;
EdgeWeight duration;
unsigned source_name_id;
unsigned target_name_id;
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
void BuildDurationAndLengthStrings(const double distance, const unsigned time)
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
{
// compute distance/duration for route summary
intToString(round(distance), lengthString);
int travel_time = round(time / 10.);
intToString(std::max(travel_time, 1), durationString);
distance = round(raw_distance);
duration = round(raw_duration / 10.);
}
} summary;
@@ -79,13 +78,12 @@ class DescriptionFactory
DescriptionFactory();
virtual ~DescriptionFactory();
double GetBearing(const FixedPointCoordinate &C, const FixedPointCoordinate &B) const;
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
JSON::Value AppendUnencodedPolylineString() const;
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode &start_phantom);
void SetEndSegment(const PhantomNode &start_phantom);
void AppendEncodedPolylineString(const bool return_encoded, std::vector<std::string> &output);
JSON::Value AppendEncodedPolylineString(const bool return_encoded);
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
{
@@ -198,7 +196,7 @@ class DescriptionFactory
{
if (path_description[i].necessary)
{
double angle =
const double angle =
GetBearing(path_description[i].location, path_description[i + 1].location);
path_description[i].bearing = angle * 10;
}
+38 -35
View File
@@ -36,7 +36,24 @@ template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFac
DescriptorConfig config;
FixedPointCoordinate current;
std::string tmp;
void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
{
const std::string route_point_head = "<rtept lat=\"";
const std::string route_point_middle = " lon=\"";
const std::string route_point_tail = "\"></rtept>";
std::string tmp;
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
output.insert(output.end(), route_point_head.begin(), route_point_head.end());
output.insert(output.end(), tmp.begin(), tmp.end());
output.push_back('\"');
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
output.insert(output.end(), tmp.begin(), tmp.end());
output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
}
public:
void SetConfig(const DescriptorConfig &c) { config = c; }
@@ -47,51 +64,37 @@ template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFac
DataFacadeT *facade,
http::Reply &reply)
{
reply.content.emplace_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content.emplace_back("<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
"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.emplace_back("<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>");
reply.content.emplace_back("<rte>");
bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
(!raw_route.unpacked_path_segments.front().empty());
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
"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"
"\">"
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>"
"<rte>");
reply.content.insert(reply.content.end(), header.begin(), header.end());
const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
(!raw_route.unpacked_path_segments.front().empty());
if (found_route)
{
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lat, tmp);
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lon, tmp);
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
AddRoutePoint(phantom_node_list.source_phantom.location, reply.content);
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
{
for (const PathData &path_data : path_data_vector)
{
FixedPointCoordinate current_coordinate =
const FixedPointCoordinate current_coordinate =
facade->GetCoordinateOfNode(path_data.node);
FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lat,
tmp);
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lon,
tmp);
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
AddRoutePoint(current_coordinate, reply.content);
}
}
// Add the via point or the end coordinate
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lat, tmp);
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lon, tmp);
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
AddRoutePoint(phantom_node_list.target_phantom.location, reply.content);
}
reply.content.emplace_back("</rte></gpx>");
std::string footer("</rte></gpx>");
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
}
};
#endif // GPX_DESCRIPTOR_H
+162 -225
View File
@@ -31,10 +31,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseDescriptor.h"
#include "DescriptionFactory.h"
#include "../Algorithms/ObjectToBase64.h"
#include "../DataStructures/JSONContainer.h"
#include "../DataStructures/SegmentInformation.h"
#include "../DataStructures/TurnInstructions.h"
#include "../Util/Azimuth.h"
#include "../Util/StringUtil.h"
#include "../Util/TimingUtil.h"
#include <algorithm>
@@ -45,7 +47,7 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
DataFacadeT *facade;
DescriptorConfig config;
DescriptionFactory description_factory;
DescriptionFactory alternate_descriptionFactory;
DescriptionFactory alternate_description_factory;
FixedPointCoordinate current;
unsigned entered_restricted_area_count;
struct RoundAbout
@@ -106,14 +108,15 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
DataFacadeT *f,
http::Reply &reply)
{
JSON::Object json_result;
facade = f;
reply.content.emplace_back("{\"status\":");
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
{
// We do not need to do much, if there is no route ;-)
reply.content.emplace_back(
"207,\"status_message\": \"Cannot find route between points\"}");
json_result.values["status"] = 207;
json_result.values["status_message"] = "Cannot find route between points";
JSON::render(reply.content, json_result);
return;
}
@@ -127,8 +130,8 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
raw_route.segment_end_coordinates.size());
description_factory.SetStartSegment(phantom_nodes.source_phantom);
reply.content.emplace_back("0,"
"\"status_message\": \"Found route between points\",");
json_result.values["status"] = 0;
json_result.values["status_message"] = "Found route between points";
// for each unpacked segment add the leg to the description
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
@@ -141,200 +144,151 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
description_factory.SetEndSegment(phantom_nodes.target_phantom);
description_factory.Run(facade, config.zoom_level);
reply.content.emplace_back("\"route_geometry\": ");
if (config.geometry)
{
description_factory.AppendEncodedPolylineString(config.encode_geometry, reply.content);
JSON::Value route_geometry = description_factory.AppendEncodedPolylineString(config.encode_geometry);
json_result.values["route_geometry"] = route_geometry;
}
else
{
reply.content.emplace_back("[]");
}
reply.content.emplace_back(",\"route_instructions\": [");
if (config.instructions)
{
JSON::Array json_route_instructions;
BuildTextualDescription(description_factory,
reply,
json_route_instructions,
raw_route.shortest_path_length,
facade,
shortest_path_segments);
json_result.values["route_instructions"] = json_route_instructions;
}
reply.content.emplace_back("],");
description_factory.BuildRouteSummary(description_factory.entireLength,
raw_route.shortest_path_length);
JSON::Object json_route_summary;
json_route_summary.values["total_distance"] = description_factory.summary.distance;
json_route_summary.values["total_time"] = description_factory.summary.duration;
json_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
json_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
json_result.values["route_summary"] = json_route_summary;
reply.content.emplace_back("\"route_summary\":");
reply.content.emplace_back("{");
reply.content.emplace_back("\"total_distance\":");
reply.content.emplace_back(description_factory.summary.lengthString);
reply.content.emplace_back(","
"\"total_time\":");
reply.content.emplace_back(description_factory.summary.durationString);
reply.content.emplace_back(","
"\"start_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.startName));
reply.content.emplace_back("\","
"\"end_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.emplace_back("\"");
reply.content.emplace_back("}");
reply.content.emplace_back(",");
// Get Names for both routes
RouteNames route_names;
JSON::Array json_route_names;
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, route_names);
json_route_names.values.push_back(route_names.shortest_path_name_1);
json_route_names.values.push_back(route_names.shortest_path_name_2);
json_result.values["route_name"] = json_route_names;
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
JSON::Array json_via_points_array;
JSON::Array json_first_coordinate;
json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lat/COORDINATE_PRECISION);
json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lon/COORDINATE_PRECISION);
json_via_points_array.values.push_back(json_first_coordinate);
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
{
std::string tmp;
JSON::Array json_coordinate;
json_coordinate.values.push_back(nodes.target_phantom.location.lat/COORDINATE_PRECISION);
json_coordinate.values.push_back(nodes.target_phantom.location.lon/COORDINATE_PRECISION);
json_via_points_array.values.push_back(json_coordinate);
}
json_result.values["via_points"] = json_via_points_array;
JSON::Array json_via_indices_array;
json_via_indices_array.values.insert(json_via_indices_array.values.end(), shortest_leg_end_indices.begin(), shortest_leg_end_indices.end());
json_result.values["via_indices"] = json_via_indices_array;
// only one alternative route is computed at this time, so this is hardcoded
if (raw_route.alternative_path_length != INVALID_EDGE_WEIGHT)
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom);
json_result.values["found_alternative"] = JSON::True();
alternate_description_factory.SetStartSegment(phantom_nodes.source_phantom);
// Get all the coordinates for the computed route
for (const PathData &path_data : raw_route.unpacked_alternative)
{
current = facade->GetCoordinateOfNode(path_data.node);
alternate_descriptionFactory.AppendSegment(current, path_data);
alternate_description_factory.AppendSegment(current, path_data);
}
}
alternate_descriptionFactory.Run(facade, config.zoom_level);
alternate_description_factory.Run(facade, config.zoom_level);
// //give an array of alternative routes
reply.content.emplace_back("\"alternative_geometries\": [");
if (config.geometry && INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
// Generate the linestrings for each alternative
alternate_descriptionFactory.AppendEncodedPolylineString(config.encode_geometry,
reply.content);
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"alternative_instructions\":[");
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
reply.content.emplace_back("[");
// Generate instructions for each alternative
if (config.geometry)
{
JSON::Value alternate_geometry_string = alternate_description_factory.AppendEncodedPolylineString(config.encode_geometry);
JSON::Array json_alternate_geometries_array;
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
}
// Generate instructions for each alternative (simulated here)
JSON::Array json_alt_instructions;
JSON::Array json_current_alt_instructions;
if (config.instructions)
{
BuildTextualDescription(alternate_descriptionFactory,
reply,
BuildTextualDescription(alternate_description_factory,
json_current_alt_instructions,
raw_route.alternative_path_length,
facade,
alternative_path_segments);
json_alt_instructions.values.push_back(json_current_alt_instructions);
json_result.values["alternative_instructions"] = json_alt_instructions;
}
reply.content.emplace_back("]");
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"alternative_summaries\":[");
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
// Generate route summary (length, duration) for each alternative
alternate_descriptionFactory.BuildRouteSummary(
alternate_descriptionFactory.entireLength, raw_route.alternative_path_length);
reply.content.emplace_back("{");
reply.content.emplace_back("\"total_distance\":");
reply.content.emplace_back(alternate_descriptionFactory.summary.lengthString);
reply.content.emplace_back(","
"\"total_time\":");
reply.content.emplace_back(alternate_descriptionFactory.summary.durationString);
reply.content.emplace_back(","
"\"start_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.startName));
reply.content.emplace_back("\","
"\"end_point\":\"");
reply.content.emplace_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.emplace_back("\"");
reply.content.emplace_back("}");
}
reply.content.emplace_back("],");
alternate_description_factory.BuildRouteSummary(
alternate_description_factory.entireLength, raw_route.alternative_path_length);
// //Get Names for both routes
RouteNames routeNames;
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
JSON::Object json_alternate_route_summary;
JSON::Array json_alternate_route_summary_array;
json_alternate_route_summary.values["total_distance"] = alternate_description_factory.summary.distance;
json_alternate_route_summary.values["total_time"] = alternate_description_factory.summary.duration;
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.source_name_id);
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.target_name_id);
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
reply.content.emplace_back("\"route_name\":[\"");
reply.content.emplace_back(routeNames.shortest_path_name_1);
reply.content.emplace_back("\",\"");
reply.content.emplace_back(routeNames.shortest_path_name_2);
reply.content.emplace_back("\"],"
"\"alternative_names\":[");
reply.content.emplace_back("[\"");
reply.content.emplace_back(routeNames.alternative_path_name_1);
reply.content.emplace_back("\",\"");
reply.content.emplace_back(routeNames.alternative_path_name_2);
reply.content.emplace_back("\"]");
reply.content.emplace_back("],");
// list all viapoints so that the client may display it
reply.content.emplace_back("\"via_points\":[");
JSON::Array json_altenative_indices_array;
json_altenative_indices_array.values.push_back(0);
json_altenative_indices_array.values.push_back(alternate_description_factory.path_description.size());
json_result.values["alternative_indices"] = json_altenative_indices_array;
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
JSON::Array json_alternate_names_array;
JSON::Array json_alternate_names;
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
json_alternate_names_array.values.push_back(json_alternate_names);
json_result.values["alternative_names"] = json_alternate_names_array;
std::string tmp;
FixedPointCoordinate::convertInternalReversedCoordinateToString(
raw_route.segment_end_coordinates.front().source_phantom.location, tmp);
reply.content.emplace_back("[");
reply.content.emplace_back(tmp);
reply.content.emplace_back("]");
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
{
tmp.clear();
FixedPointCoordinate::convertInternalReversedCoordinateToString(
nodes.target_phantom.location, tmp);
reply.content.emplace_back(",[");
reply.content.emplace_back(tmp);
reply.content.emplace_back("]");
} else {
json_result.values["found_alternative"] = JSON::False();
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"via_indices\":[");
for (const unsigned index : shortest_leg_end_indices)
{
tmp.clear();
intToString(index, tmp);
reply.content.emplace_back(tmp);
if (index != shortest_leg_end_indices.back())
{
reply.content.emplace_back(",");
}
}
reply.content.emplace_back("],\"alternative_indices\":[");
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
{
reply.content.emplace_back("0,");
tmp.clear();
intToString(alternate_descriptionFactory.path_description.size(), tmp);
reply.content.emplace_back(tmp);
}
reply.content.emplace_back("],");
reply.content.emplace_back("\"hint_data\": {");
reply.content.emplace_back("\"checksum\":");
intToString(raw_route.check_sum, tmp);
reply.content.emplace_back(tmp);
reply.content.emplace_back(", \"locations\": [");
JSON::Object json_hint_object;
json_hint_object.values["checksum"] = raw_route.check_sum;
JSON::Array json_location_hint_array;
std::string hint;
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
{
reply.content.emplace_back("\"");
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
reply.content.emplace_back(hint);
reply.content.emplace_back("\", ");
json_location_hint_array.values.push_back(hint);
}
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
reply.content.emplace_back("\"");
reply.content.emplace_back(hint);
reply.content.emplace_back("\"]");
reply.content.emplace_back("}}");
json_location_hint_array.values.push_back(hint);
json_hint_object.values["locations"] = json_location_hint_array;
json_result.values["hint_data"] = json_hint_object;
// render the content to the output array
TIMER_START(route_render);
JSON::render(reply.content, json_result);
TIMER_STOP(route_render);
JSON::render(SimpleLogger().Write(), json_result);
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
}
// TODO: break into function object with several functions, i.e. simplify
// construct routes names
void GetRouteNames(std::vector<Segment> &shortest_path_segments,
std::vector<Segment> &alternative_path_segments,
const DataFacadeT *facade,
RouteNames &routeNames)
RouteNames &route_names)
{
Segment shortest_segment_1, shortest_segment_2;
Segment alternativeSegment1, alternative_segment_2;
Segment alternative_segment_1, alternative_segment_2;
auto length_comperator = [](Segment a, Segment b)
{ return a.length < b.length; };
@@ -351,28 +305,28 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
std::sort(alternative_path_segments.begin(),
alternative_path_segments.end(),
length_comperator);
alternativeSegment1 = alternative_path_segments[0];
alternative_segment_1 = alternative_path_segments[0];
}
std::vector<Segment> shortestDifference(shortest_path_segments.size());
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
std::vector<Segment> shortest_path_set_difference(shortest_path_segments.size());
std::vector<Segment> alternative_path_set_difference(alternative_path_segments.size());
std::set_difference(shortest_path_segments.begin(),
shortest_path_segments.end(),
alternative_path_segments.begin(),
alternative_path_segments.end(),
shortestDifference.begin(),
shortest_path_set_difference.begin(),
length_comperator);
int size_of_difference = shortestDifference.size();
int size_of_difference = shortest_path_set_difference.size();
if (size_of_difference)
{
int i = 0;
while (i < size_of_difference &&
shortestDifference[i].name_id == shortest_path_segments[0].name_id)
shortest_path_set_difference[i].name_id == shortest_path_segments[0].name_id)
{
++i;
}
if (i < size_of_difference)
{
shortest_segment_2 = shortestDifference[i];
shortest_segment_2 = shortest_path_set_difference[i];
}
}
@@ -380,50 +334,51 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
alternative_path_segments.end(),
shortest_path_segments.begin(),
shortest_path_segments.end(),
alternativeDifference.begin(),
alternative_path_set_difference.begin(),
name_id_comperator);
size_of_difference = alternativeDifference.size();
size_of_difference = alternative_path_set_difference.size();
if (size_of_difference)
{
int i = 0;
while (i < size_of_difference &&
alternativeDifference[i].name_id == alternative_path_segments[0].name_id)
alternative_path_set_difference[i].name_id == alternative_path_segments[0].name_id)
{
++i;
}
if (i < size_of_difference)
{
alternative_segment_2 = alternativeDifference[i];
alternative_segment_2 = alternative_path_set_difference[i];
}
}
if (shortest_segment_1.position > shortest_segment_2.position)
{
std::swap(shortest_segment_1, shortest_segment_2);
if (alternativeSegment1.position > alternative_segment_2.position)
std::swap(alternativeSegment1, alternative_segment_2);
routeNames.shortest_path_name_1 =
}
if (alternative_segment_1.position > alternative_segment_2.position)
{
std::swap(alternative_segment_1, alternative_segment_2);
}
route_names.shortest_path_name_1 =
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
routeNames.shortest_path_name_2 =
route_names.shortest_path_name_2 =
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
routeNames.alternative_path_name_1 =
facade->GetEscapedNameForNameID(alternativeSegment1.name_id);
routeNames.alternative_path_name_2 =
route_names.alternative_path_name_1 =
facade->GetEscapedNameForNameID(alternative_segment_1.name_id);
route_names.alternative_path_name_2 =
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
}
}
// TODO: reorder parameters
inline void BuildTextualDescription(DescriptionFactory &description_factory,
http::Reply &reply,
JSON::Array & json_instruction_array,
const int route_length,
const DataFacadeT *facade,
std::vector<Segment> &route_segments_list)
{
// 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]
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
unsigned necessary_segments_running_index = 0;
round_about.leave_at_exit = 0;
round_about.name_id = 0;
@@ -432,6 +387,7 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
// Fetch data from Factory and generate a string from it.
for (const SegmentInformation &segment : description_factory.path_description)
{
JSON::Array json_instruction_row;
TurnInstruction current_instruction = segment.turn_instruction;
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
@@ -443,50 +399,35 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
}
else
{
if (necessary_segments_running_index)
{
reply.content.emplace_back(",");
}
reply.content.emplace_back("[\"");
std::string current_turn_instruction;
if (TurnInstruction::LeaveRoundAbout == current_instruction)
{
intToString(as_integer(TurnInstruction::EnterRoundAbout), temp_instruction);
reply.content.emplace_back(temp_instruction);
reply.content.emplace_back("-");
intToString(round_about.leave_at_exit + 1, temp_instruction);
reply.content.emplace_back(temp_instruction);
temp_instruction = IntToString(as_integer(TurnInstruction::EnterRoundAbout));
current_turn_instruction += temp_instruction;
current_turn_instruction += "-";
temp_instruction = IntToString(round_about.leave_at_exit + 1);
current_turn_instruction += temp_instruction;
round_about.leave_at_exit = 0;
}
else
{
intToString(as_integer(current_instruction), temp_instruction);
reply.content.emplace_back(temp_instruction);
temp_instruction = IntToString(as_integer(current_instruction));
current_turn_instruction += temp_instruction;
}
json_instruction_row.values.push_back(current_turn_instruction);
reply.content.emplace_back("\",\"");
reply.content.emplace_back(facade->GetEscapedNameForNameID(segment.name_id));
reply.content.emplace_back("\",");
intToString(segment.length, temp_dist);
reply.content.emplace_back(temp_dist);
reply.content.emplace_back(",");
intToString(necessary_segments_running_index, temp_length);
reply.content.emplace_back(temp_length);
reply.content.emplace_back(",");
intToString(round(segment.duration / 10.), temp_duration);
reply.content.emplace_back(temp_duration);
reply.content.emplace_back(",\"");
intToString(segment.length, temp_length);
reply.content.emplace_back(temp_length);
reply.content.emplace_back("m\",\"");
json_instruction_row.values.push_back(facade->GetEscapedNameForNameID(segment.name_id));
json_instruction_row.values.push_back(std::round(segment.length));
json_instruction_row.values.push_back(necessary_segments_running_index);
json_instruction_row.values.push_back(round(segment.duration / 10));
json_instruction_row.values.push_back(IntToString(segment.length)+"m");
int bearing_value = round(segment.bearing / 10.);
reply.content.emplace_back(Azimuth::Get(bearing_value));
reply.content.emplace_back("\",");
intToString(bearing_value, temp_bearing);
reply.content.emplace_back(temp_bearing);
reply.content.emplace_back("]");
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
json_instruction_row.values.push_back(bearing_value);
route_segments_list.emplace_back(
Segment(segment.name_id, segment.length, route_segments_list.size()));
segment.name_id, segment.length, route_segments_list.size());
json_instruction_array.values.push_back(json_instruction_row);
}
}
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
@@ -498,25 +439,21 @@ template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFa
++necessary_segments_running_index;
}
}
//TODO: check if this in an invariant
if (INVALID_EDGE_WEIGHT != route_length)
{
reply.content.emplace_back(",[\"");
intToString(as_integer(TurnInstruction::ReachedYourDestination), temp_instruction);
reply.content.emplace_back(temp_instruction);
reply.content.emplace_back("\",\"");
reply.content.emplace_back("\",");
reply.content.emplace_back("0");
reply.content.emplace_back(",");
intToString(necessary_segments_running_index - 1, temp_length);
reply.content.emplace_back(temp_length);
reply.content.emplace_back(",");
reply.content.emplace_back("0");
reply.content.emplace_back(",\"");
reply.content.emplace_back("\",\"");
reply.content.emplace_back(Azimuth::Get(0.0));
reply.content.emplace_back("\",");
reply.content.emplace_back("0.0");
reply.content.emplace_back("]");
JSON::Array json_last_instruction_row;
temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
json_last_instruction_row.values.push_back(temp_instruction);
json_last_instruction_row.values.push_back("");
json_last_instruction_row.values.push_back(0);
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
json_last_instruction_row.values.push_back(0);
json_last_instruction_row.values.push_back("0m");
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
json_last_instruction_row.values.push_back(0.);
json_instruction_array.values.push_back(json_last_instruction_row);
}
}
};