(partially) migrate Descriptors to use C++11 syntax

This commit is contained in:
Dennis Luxen 2014-05-02 19:07:55 +02:00
parent 946bfb9a26
commit 17ed4f908c
5 changed files with 423 additions and 452 deletions

View File

@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef BASE_DESCRIPTOR_H_ #ifndef BASE_DESCRIPTOR_H
#define BASE_DESCRIPTOR_H_ #define BASE_DESCRIPTOR_H
#include "../DataStructures/PhantomNodes.h" #include "../DataStructures/PhantomNodes.h"
#include "../DataStructures/RawRouteData.h" #include "../DataStructures/RawRouteData.h"
@ -37,32 +37,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <vector> #include <vector>
struct DescriptorConfig { struct DescriptorConfig
DescriptorConfig() : {
instructions(true), DescriptorConfig() : instructions(true), geometry(true), encode_geometry(true), zoom_level(18)
geometry(true), {
encode_geometry(true), }
zoom_level(18)
{ }
bool instructions; bool instructions;
bool geometry; bool geometry;
bool encode_geometry; bool encode_geometry;
unsigned short zoom_level; unsigned short zoom_level;
}; };
template<class DataFacadeT> template <class DataFacadeT> class BaseDescriptor
class BaseDescriptor { {
public: public:
BaseDescriptor() { } BaseDescriptor() {}
//Maybe someone can explain the pure virtual destructor thing to me (dennis) // Maybe someone can explain the pure virtual destructor thing to me (dennis)
virtual ~BaseDescriptor() { } virtual ~BaseDescriptor() {}
virtual void Run( virtual void Run(const RawRouteData &raw_route,
const RawRouteData & rawRoute, const PhantomNodes &phantom_nodes,
const PhantomNodes & phantomNodes, DataFacadeT *facade,
DataFacadeT * facade, http::Reply &reply) = 0;
http::Reply & reply virtual void SetConfig(const DescriptorConfig &config) = 0;
) = 0;
virtual void SetConfig(const DescriptorConfig & config) = 0;
}; };
#endif /* BASE_DESCRIPTOR_H_ */ #endif // BASE_DESCRIPTOR_H

View File

@ -27,26 +27,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "DescriptionFactory.h" #include "DescriptionFactory.h"
DescriptionFactory::DescriptionFactory() : entireLength(0) { } DescriptionFactory::DescriptionFactory() : entireLength(0) {}
DescriptionFactory::~DescriptionFactory() { } DescriptionFactory::~DescriptionFactory() {}
inline double DescriptionFactory::DegreeToRadian(const double degree) const inline double DescriptionFactory::DegreeToRadian(const double degree) const
{ {
return degree * (M_PI/180.); return degree * (M_PI / 180.);
} }
inline double DescriptionFactory::RadianToDegree(const double radian) const inline double DescriptionFactory::RadianToDegree(const double radian) const
{ {
return radian * (180./M_PI); return radian * (180. / M_PI);
} }
double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const double DescriptionFactory::GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B)
const
{ {
double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION); double delta_long = DegreeToRadian(B.lon / COORDINATE_PRECISION - A.lon / COORDINATE_PRECISION);
const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION); const double lat1 = DegreeToRadian(A.lat / COORDINATE_PRECISION);
const double lat2 = DegreeToRadian(B.lat/COORDINATE_PRECISION); const double lat2 = DegreeToRadian(B.lat / COORDINATE_PRECISION);
const double y = sin(delta_long) * cos(lat2); const double y = sin(delta_long) * cos(lat2);
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long); const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
@ -63,77 +64,69 @@ double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const Fixe
return result; return result;
} }
void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse) void DescriptionFactory::SetStartSegment(const PhantomNode &source,
const bool source_traversed_in_reverse)
{ {
start_phantom = source; start_phantom = source;
AppendSegment( AppendSegment(source.location, PathData(0, source.name_id, 10, source.forward_weight));
source.location,
PathData(0, source.name_id, 10, source.forward_weight)
);
} }
void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse) void DescriptionFactory::SetEndSegment(const PhantomNode &target,
const bool target_traversed_in_reverse)
{ {
target_phantom = target; target_phantom = target;
pathDescription.push_back( path_description.push_back(
SegmentInformation( SegmentInformation(target.location, target.name_id, 0, target.reverse_weight, 0, true));
target.location,
target.name_id,
0,
target.reverse_weight,
0,
true
)
);
} }
void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point) void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
const PathData &path_point)
{ {
if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate)) if ((1 == path_description.size()) && (path_description.back().location == coordinate))
{ {
pathDescription.back().name_id = path_point.name_id; path_description.back().name_id = path_point.name_id;
} }
else else
{ {
pathDescription.push_back( path_description.push_back(SegmentInformation(coordinate,
SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction) path_point.name_id,
); path_point.durationOfSegment,
0,
path_point.turnInstruction));
} }
} }
void DescriptionFactory::AppendEncodedPolylineString( void DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded,
const bool return_encoded, std::vector<std::string> &output)
std::vector<std::string> & output {
) {
std::string temp; std::string temp;
if(return_encoded) { if (return_encoded)
polyline_compressor.printEncodedString(pathDescription, temp); {
} else { polyline_compressor.printEncodedString(path_description, temp);
polyline_compressor.printUnencodedString(pathDescription, temp); }
else
{
polyline_compressor.printUnencodedString(path_description, temp);
} }
output.push_back(temp); output.push_back(temp);
} }
void DescriptionFactory::AppendEncodedPolylineString( void DescriptionFactory::AppendEncodedPolylineString(std::vector<std::string> &output) const
std::vector<std::string> &output {
) const {
std::string temp; std::string temp;
polyline_compressor.printEncodedString(pathDescription, temp); polyline_compressor.printEncodedString(path_description, temp);
output.push_back(temp); output.push_back(temp);
} }
void DescriptionFactory::AppendUnencodedPolylineString( void DescriptionFactory::AppendUnencodedPolylineString(std::vector<std::string> &output) const
std::vector<std::string>& output {
) const {
std::string temp; std::string temp;
polyline_compressor.printUnencodedString(pathDescription, temp); polyline_compressor.printUnencodedString(path_description, temp);
output.push_back(temp); output.push_back(temp);
} }
void DescriptionFactory::BuildRouteSummary( void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
const double distance, {
const unsigned time
) {
summary.startName = start_phantom.name_id; summary.startName = start_phantom.name_id;
summary.destName = target_phantom.name_id; summary.destName = target_phantom.name_id;
summary.BuildDurationAndLengthStrings(distance, time); summary.BuildDurationAndLengthStrings(distance, time);

View File

@ -45,71 +45,63 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* This class is fed with all way segments in consecutive order /* This class is fed with all way segments in consecutive order
* and produces the description plus the encoded polyline */ * and produces the description plus the encoded polyline */
class DescriptionFactory { class DescriptionFactory
{
DouglasPeucker polyline_generalizer; DouglasPeucker polyline_generalizer;
PolylineCompressor polyline_compressor; PolylineCompressor polyline_compressor;
PhantomNode start_phantom, target_phantom; PhantomNode start_phantom, target_phantom;
double DegreeToRadian(const double degree) const; double DegreeToRadian(const double degree) const;
double RadianToDegree(const double degree) const; double RadianToDegree(const double degree) const;
public:
struct RouteSummary { public:
struct RouteSummary
{
std::string lengthString; std::string lengthString;
std::string durationString; std::string durationString;
unsigned startName; unsigned startName;
unsigned destName; unsigned destName;
RouteSummary() : RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
lengthString("0"),
durationString("0"),
startName(0),
destName(0)
{}
void BuildDurationAndLengthStrings( void BuildDurationAndLengthStrings(const double distance, const unsigned time)
const double distance, {
const unsigned time // compute distance/duration for route summary
) {
//compute distance/duration for route summary
intToString(round(distance), lengthString); intToString(round(distance), lengthString);
int travel_time = round(time/10.); int travel_time = round(time / 10.);
intToString(std::max(travel_time, 1), durationString); intToString(std::max(travel_time, 1), durationString);
} }
} summary; } summary;
double entireLength; double entireLength;
//I know, declaring this public is considered bad. I'm lazy // I know, declaring this public is considered bad. I'm lazy
std::vector <SegmentInformation> pathDescription; std::vector<SegmentInformation> path_description;
DescriptionFactory(); DescriptionFactory();
virtual ~DescriptionFactory(); virtual ~DescriptionFactory();
double GetBearing(const FixedPointCoordinate& C, const FixedPointCoordinate& B) const; double GetBearing(const FixedPointCoordinate &C, const FixedPointCoordinate &B) const;
void AppendEncodedPolylineString(std::vector<std::string> &output) const; void AppendEncodedPolylineString(std::vector<std::string> &output) const;
void AppendUnencodedPolylineString(std::vector<std::string> &output) const; void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data); void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
void BuildRouteSummary(const double distance, const unsigned time); void BuildRouteSummary(const double distance, const unsigned time);
void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse); void SetStartSegment(const PhantomNode &start_phantom, const bool source_traversed_in_reverse);
void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse); void SetEndSegment(const PhantomNode &start_phantom, const bool target_traversed_in_reverse);
void AppendEncodedPolylineString( void AppendEncodedPolylineString(const bool return_encoded, std::vector<std::string> &output);
const bool return_encoded,
std::vector<std::string> & output
);
template<class DataFacadeT> template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
void Run( {
const DataFacadeT * facade, if (path_description.empty())
const unsigned zoomLevel {
) {
if( pathDescription.empty() ) {
return; return;
} }
/** starts at index 1 */ /** starts at index 1 */
pathDescription[0].length = 0; path_description[0].length = 0;
for (unsigned i = 1; i < pathDescription.size(); ++i) for (unsigned i = 1; i < path_description.size(); ++i)
{ {
//move down names by one, q&d hack // move down names by one, q&d hack
pathDescription[i-1].name_id = pathDescription[i].name_id; path_description[i - 1].name_id = path_description[i].name_id;
pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location); path_description[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(
path_description[i - 1].location, path_description[i].location);
} }
/*Simplify turn instructions /*Simplify turn instructions
@ -121,84 +113,94 @@ public:
becomes: becomes:
10. Turn left on B 36 for 35 km 10. Turn left on B 36 for 35 km
*/ */
//TODO: rework to check only end and start of string. // TODO: rework to check only end and start of string.
// stl string is way to expensive // stl string is way to expensive
// unsigned lastTurn = 0; // unsigned lastTurn = 0;
// for(unsigned i = 1; i < pathDescription.size(); ++i) { // for(unsigned i = 1; i < path_description.size(); ++i) {
// string1 = sEngine.GetEscapedNameForNameID(pathDescription[i].name_id); // string1 = sEngine.GetEscapedNameForNameID(path_description[i].name_id);
// if(TurnInstructionsClass::GoStraight == pathDescription[i].turn_instruction) { // if(TurnInstructionsClass::GoStraight == path_description[i].turn_instruction) {
// if(std::string::npos != string0.find(string1+";") // if(std::string::npos != string0.find(string1+";")
// || std::string::npos != string0.find(";"+string1) // || std::string::npos != string0.find(";"+string1)
// || std::string::npos != string0.find(string1+" ;") // || std::string::npos != string0.find(string1+" ;")
// || std::string::npos != string0.find("; "+string1) // || std::string::npos != string0.find("; "+string1)
// ){ // ){
// SimpleLogger().Write() << "->next correct: " << string0 << " contains " << string1; // SimpleLogger().Write() << "->next correct: " << string0 << " contains " <<
// for(; lastTurn != i; ++lastTurn) // string1;
// pathDescription[lastTurn].name_id = pathDescription[i].name_id; // for(; lastTurn != i; ++lastTurn)
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn; // path_description[lastTurn].name_id = path_description[i].name_id;
// } else if(std::string::npos != string1.find(string0+";") // path_description[i].turn_instruction = TurnInstructionsClass::NoTurn;
// || std::string::npos != string1.find(";"+string0) // } else if(std::string::npos != string1.find(string0+";")
// || std::string::npos != string1.find(string0+" ;") // || std::string::npos != string1.find(";"+string0)
// || std::string::npos != string1.find("; "+string0) // || std::string::npos != string1.find(string0+" ;")
// ){ // || std::string::npos != string1.find("; "+string0)
// SimpleLogger().Write() << "->prev correct: " << string1 << " contains " << string0; // ){
// pathDescription[i].name_id = pathDescription[i-1].name_id; // SimpleLogger().Write() << "->prev correct: " << string1 << " contains " <<
// pathDescription[i].turn_instruction = TurnInstructionsClass::NoTurn; // string0;
// } // path_description[i].name_id = path_description[i-1].name_id;
// } // path_description[i].turn_instruction = TurnInstructionsClass::NoTurn;
// if (TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) { // }
// lastTurn = i; // }
// } // if (TurnInstructionsClass::NoTurn != path_description[i].turn_instruction) {
// string0 = string1; // lastTurn = i;
// } // }
// string0 = string1;
// }
double segment_length = 0.; double segment_length = 0.;
unsigned segment_duration = 0; unsigned segment_duration = 0;
unsigned segment_start_index = 0; unsigned segment_start_index = 0;
for(unsigned i = 1; i < pathDescription.size(); ++i) { for (unsigned i = 1; i < path_description.size(); ++i)
entireLength += pathDescription[i].length; {
segment_length += pathDescription[i].length; entireLength += path_description[i].length;
segment_duration += pathDescription[i].duration; segment_length += path_description[i].length;
pathDescription[segment_start_index].length = segment_length; segment_duration += path_description[i].duration;
pathDescription[segment_start_index].duration = segment_duration; path_description[segment_start_index].length = segment_length;
path_description[segment_start_index].duration = segment_duration;
if (TurnInstructionsClass::NoTurn != path_description[i].turn_instruction)
if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) { {
BOOST_ASSERT(pathDescription[i].necessary); BOOST_ASSERT(path_description[i].necessary);
segment_length = 0; segment_length = 0;
segment_duration = 0; segment_duration = 0;
segment_start_index = i; segment_start_index = i;
} }
} }
//Post-processing to remove empty or nearly empty path segments // Post-processing to remove empty or nearly empty path segments
if(std::numeric_limits<double>::epsilon() > pathDescription.back().length) { if (std::numeric_limits<double>::epsilon() > path_description.back().length)
if(pathDescription.size() > 2){ {
pathDescription.pop_back(); if (path_description.size() > 2)
pathDescription.back().necessary = true; {
pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn; path_description.pop_back();
target_phantom.name_id = (pathDescription.end()-2)->name_id; path_description.back().necessary = true;
path_description.back().turn_instruction = TurnInstructionsClass::NoTurn;
target_phantom.name_id = (path_description.end() - 2)->name_id;
} }
} }
if(std::numeric_limits<double>::epsilon() > pathDescription[0].length) { if (std::numeric_limits<double>::epsilon() > path_description[0].length)
if(pathDescription.size() > 2) { {
pathDescription.erase(pathDescription.begin()); if (path_description.size() > 2)
pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn; {
pathDescription[0].necessary = true; path_description.erase(path_description.begin());
start_phantom.name_id = pathDescription[0].name_id; path_description[0].turn_instruction = TurnInstructionsClass::HeadOn;
path_description[0].necessary = true;
start_phantom.name_id = path_description[0].name_id;
} }
} }
//Generalize poly line // Generalize poly line
polyline_generalizer.Run(pathDescription, zoomLevel); polyline_generalizer.Run(path_description, zoomLevel);
//fix what needs to be fixed else // fix what needs to be fixed else
for(unsigned i = 0; i < pathDescription.size()-1 && pathDescription.size() >= 2; ++i){ for (unsigned i = 0; i < path_description.size() - 1 && path_description.size() >= 2; ++i)
if(pathDescription[i].necessary) { {
double angle = GetBearing(pathDescription[i].location, pathDescription[i+1].location); if (path_description[i].necessary)
pathDescription[i].bearing = angle*10; {
double angle =
GetBearing(path_description[i].location, path_description[i + 1].location);
path_description[i].bearing = angle * 10;
} }
} }
return; return;

View File

@ -25,82 +25,72 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef GPX_DESCRIPTOR_H_ #ifndef GPX_DESCRIPTOR_H
#define GPX_DESCRIPTOR_H_ #define GPX_DESCRIPTOR_H
#include "BaseDescriptor.h" #include "BaseDescriptor.h"
#include <boost/foreach.hpp> template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFacadeT>
{
template<class DataFacadeT> private:
class GPXDescriptor : public BaseDescriptor<DataFacadeT> {
private:
DescriptorConfig config; DescriptorConfig config;
FixedPointCoordinate current; FixedPointCoordinate current;
std::string tmp; std::string tmp;
public:
void SetConfig(const DescriptorConfig & c) { config = c; }
//TODO: reorder parameters public:
void Run( void SetConfig(const DescriptorConfig &c) { config = c; }
const RawRouteData &raw_route,
const PhantomNodes &phantom_node_list, // TODO: reorder parameters
DataFacadeT * facade, void Run(const RawRouteData &raw_route,
http::Reply & reply const PhantomNodes &phantom_node_list,
) { DataFacadeT *facade,
http::Reply &reply)
{
reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); reply.content.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
reply.content.push_back( reply.content.push_back("<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" " "xmlns=\"http://www.topografix.com/GPX/1/1\" "
"xmlns=\"http://www.topografix.com/GPX/1/1\" " "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd" "\">");
"\">"); reply.content.push_back("<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
reply.content.push_back( " OpenStreetMap contributors (ODbL)</license></copyright>"
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)" "</metadata>");
" OpenStreetMap contributors (ODbL)</license></copyright>"
"</metadata>");
reply.content.push_back("<rte>"); reply.content.push_back("<rte>");
bool found_route = (raw_route.lengthOfShortestPath != INT_MAX) && bool found_route = (raw_route.lengthOfShortestPath != INVALID_EDGE_WEIGHT) &&
(raw_route.unpacked_path_segments[0].size()); (!raw_route.unpacked_path_segments.front().empty());
if( found_route ) { if (found_route)
{
FixedPointCoordinate::convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lat, phantom_node_list.source_phantom.location.lat, tmp);
tmp
);
reply.content.push_back("<rtept lat=\"" + tmp + "\" "); reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.source_phantom.location.lon, phantom_node_list.source_phantom.location.lon, tmp);
tmp
);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>"); reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
for(unsigned i=0; i < raw_route.unpacked_path_segments.size(); ++i){ for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
BOOST_FOREACH( {
const PathData & pathData, for (const PathData &path_data : path_data_vector)
raw_route.unpacked_path_segments[i] {
) { FixedPointCoordinate current_coordinate = facade->GetCoordinateOfNode(path_data.node);
current = facade->GetCoordinateOfNode(pathData.node);
FixedPointCoordinate::convertInternalLatLonToString(current.lat, tmp); FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lat,
tmp);
reply.content.push_back("<rtept lat=\"" + tmp + "\" "); reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString(current.lon, tmp); FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lon,
tmp);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>"); reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
} }
} }
// Add the via point or the end coordinate // Add the via point or the end coordinate
FixedPointCoordinate::convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lat, phantom_node_list.target_phantom.location.lat, tmp);
tmp
);
reply.content.push_back("<rtept lat=\"" + tmp + "\" "); reply.content.push_back("<rtept lat=\"" + tmp + "\" ");
FixedPointCoordinate::convertInternalLatLonToString( FixedPointCoordinate::convertInternalLatLonToString(
phantom_node_list.target_phantom.location.lon, phantom_node_list.target_phantom.location.lon, tmp);
tmp
);
reply.content.push_back("lon=\"" + tmp + "\"></rtept>"); reply.content.push_back("lon=\"" + tmp + "\"></rtept>");
} }
reply.content.push_back("</rte></gpx>"); reply.content.push_back("</rte></gpx>");
} }
}; };
#endif // GPX_DESCRIPTOR_H_ #endif // GPX_DESCRIPTOR_H

View File

@ -36,33 +36,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../Util/Azimuth.h" #include "../Util/Azimuth.h"
#include "../Util/StringUtil.h" #include "../Util/StringUtil.h"
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <algorithm> #include <algorithm>
template<class DataFacadeT> template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
class JSONDescriptor : public BaseDescriptor<DataFacadeT> { {
private: private:
// TODO: initalize in c'tor // TODO: initalize in c'tor
DataFacadeT * facade; DataFacadeT *facade;
DescriptorConfig config; DescriptorConfig config;
DescriptionFactory description_factory; DescriptionFactory description_factory;
DescriptionFactory alternate_descriptionFactory; DescriptionFactory alternate_descriptionFactory;
FixedPointCoordinate current; FixedPointCoordinate current;
unsigned entered_restricted_area_count; unsigned entered_restricted_area_count;
struct RoundAbout{ struct RoundAbout
RoundAbout() : {
start_index(INT_MAX), RoundAbout() : start_index(INT_MAX), name_id(INT_MAX), leave_at_exit(INT_MAX) {}
name_id(INT_MAX),
leave_at_exit(INT_MAX)
{}
int start_index; int start_index;
int name_id; int name_id;
int leave_at_exit; int leave_at_exit;
} round_about; } round_about;
struct Segment { struct Segment
{
Segment() : name_id(-1), length(-1), position(-1) {} Segment() : name_id(-1), length(-1), position(-1) {}
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {} Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
int name_id; int name_id;
@ -72,219 +67,186 @@ private:
std::vector<Segment> shortest_path_segments, alternative_path_segments; std::vector<Segment> shortest_path_segments, alternative_path_segments;
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices; std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
struct RouteNames { struct RouteNames
std::string shortestPathName1; {
std::string shortestPathName2; std::string shortest_path_name_1;
std::string alternativePathName1; std::string shortest_path_name_2;
std::string alternativePathName2; std::string alternative_path_name_1;
std::string alternative_path_name_2;
}; };
public: public:
JSONDescriptor() : JSONDescriptor() : facade(nullptr), entered_restricted_area_count(0)
facade(NULL),
entered_restricted_area_count(0)
{ {
shortest_leg_end_indices.push_back(0); shortest_leg_end_indices.push_back(0);
alternative_leg_end_indices.push_back(0); alternative_leg_end_indices.push_back(0);
} }
void SetConfig(const DescriptorConfig & c) { config = c; } void SetConfig(const DescriptorConfig &c) { config = c; }
int DescribeLeg( unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
const std::vector<PathData> route_leg, {
const PhantomNodes & leg_phantoms unsigned added_element_count = 0;
) { // Get all the coordinates for the computed route
int added_element_count = 0;
//Get all the coordinates for the computed route
FixedPointCoordinate current_coordinate; FixedPointCoordinate current_coordinate;
BOOST_FOREACH(const PathData & path_data, route_leg) { for (const PathData &path_data : route_leg)
{
current_coordinate = facade->GetCoordinateOfNode(path_data.node); current_coordinate = facade->GetCoordinateOfNode(path_data.node);
description_factory.AppendSegment(current_coordinate, path_data); description_factory.AppendSegment(current_coordinate, path_data);
++added_element_count; ++added_element_count;
} }
// description_factory.SetEndSegment( leg_phantoms.target_phantom ); // description_factory.SetEndSegment( leg_phantoms.target_phantom );
++added_element_count; ++added_element_count;
BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count ); BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
return added_element_count; return added_element_count;
} }
void Run( void Run(const RawRouteData &raw_route,
const RawRouteData & raw_route, const PhantomNodes &phantom_nodes,
const PhantomNodes & phantom_nodes, // TODO: move facade initalization to c'tor
// TODO: move facade initalization to c'tor DataFacadeT *f,
DataFacadeT * f, http::Reply &reply)
http::Reply & reply {
) {
facade = f; facade = f;
reply.content.push_back( reply.content.push_back("{\"status\":");
"{\"status\":"
);
if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath) if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath)
{ {
//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.push_back( reply.content.push_back(
"207,\"status_message\": \"Cannot find route between points\"}" "207,\"status_message\": \"Cannot find route between points\"}");
);
return; return;
} }
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath; SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath;
//check if first segment is non-zero // check if first segment is non-zero
std::string road_name; std::string road_name =
road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id); facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
raw_route.segmentEndCoordinates.size());
description_factory.SetStartSegment(phantom_nodes.source_phantom,
raw_route.source_traversed_in_reverse);
reply.content.push_back("0,"
"\"status_message\": \"Found route between points\",");
// for each unpacked segment add the leg to the description // for each unpacked segment add the leg to the description
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i) for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{ {
const std::vector<PathData> & leg_path = raw_route.unpacked_path_segments[i]; const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
FixedPointCoordinate current_coordinate; raw_route.segmentEndCoordinates[i]);
BOOST_FOREACH(const PathData & path_data, leg_path) BOOST_ASSERT(0 < added_segments);
{ shortest_leg_end_indices.push_back(added_segments + shortest_leg_end_indices.back());
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
road_name = facade->GetEscapedNameForNameID(path_data.name_id);
}
} }
description_factory.SetEndSegment(phantom_nodes.target_phantom,
//check if last segment is non-zero raw_route.target_traversed_in_reverse);
road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id);
description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse);
reply.content.push_back("0,"
"\"status_message\": \"Found route between points\",");
BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() );
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
{
const int added_segments = DescribeLeg(
raw_route.unpacked_path_segments[i],
raw_route.segmentEndCoordinates[i]
);
BOOST_ASSERT( 0 < added_segments );
shortest_leg_end_indices.push_back(
added_segments + shortest_leg_end_indices.back()
);
}
description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse);
description_factory.Run(facade, config.zoom_level); description_factory.Run(facade, config.zoom_level);
reply.content.push_back("\"route_geometry\": "); reply.content.push_back("\"route_geometry\": ");
if(config.geometry) { if (config.geometry)
description_factory.AppendEncodedPolylineString( {
config.encode_geometry, description_factory.AppendEncodedPolylineString(config.encode_geometry, reply.content);
reply.content }
); else
} else { {
reply.content.push_back("[]"); reply.content.push_back("[]");
} }
reply.content.push_back(",\"route_instructions\": ["); reply.content.push_back(",\"route_instructions\": [");
if(config.instructions) { if (config.instructions)
BuildTextualDescription( {
description_factory, BuildTextualDescription(description_factory,
reply, reply,
raw_route.lengthOfShortestPath, raw_route.lengthOfShortestPath,
facade, facade,
shortest_path_segments shortest_path_segments);
);
} }
reply.content.push_back("],"); reply.content.push_back("],");
description_factory.BuildRouteSummary( description_factory.BuildRouteSummary(description_factory.entireLength,
description_factory.entireLength, raw_route.lengthOfShortestPath);
raw_route.lengthOfShortestPath
);
reply.content.push_back("\"route_summary\":"); reply.content.push_back("\"route_summary\":");
reply.content.push_back("{"); reply.content.push_back("{");
reply.content.push_back("\"total_distance\":"); reply.content.push_back("\"total_distance\":");
reply.content.push_back(description_factory.summary.lengthString); reply.content.push_back(description_factory.summary.lengthString);
reply.content.push_back("," reply.content.push_back(","
"\"total_time\":"); "\"total_time\":");
reply.content.push_back(description_factory.summary.durationString); reply.content.push_back(description_factory.summary.durationString);
reply.content.push_back("," reply.content.push_back(","
"\"start_point\":\""); "\"start_point\":\"");
reply.content.push_back( reply.content.push_back(
facade->GetEscapedNameForNameID(description_factory.summary.startName) facade->GetEscapedNameForNameID(description_factory.summary.startName));
);
reply.content.push_back("\"," reply.content.push_back("\","
"\"end_point\":\""); "\"end_point\":\"");
reply.content.push_back( reply.content.push_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName) facade->GetEscapedNameForNameID(description_factory.summary.destName));
);
reply.content.push_back("\""); reply.content.push_back("\"");
reply.content.push_back("}"); reply.content.push_back("}");
reply.content.push_back(","); reply.content.push_back(",");
//only one alternative route is computed at this time, so this is hardcoded // only one alternative route is computed at this time, so this is hardcoded
if (raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT)
{ {
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse); alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom,
//Get all the coordinates for the computed route raw_route.alt_source_traversed_in_reverse);
BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) { // Get all the coordinates for the computed route
for (const PathData &path_data : raw_route.unpacked_alternative)
{
current = facade->GetCoordinateOfNode(path_data.node); current = facade->GetCoordinateOfNode(path_data.node);
alternate_descriptionFactory.AppendSegment(current, path_data ); alternate_descriptionFactory.AppendSegment(current, path_data);
} }
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse); alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom,
raw_route.alt_target_traversed_in_reverse);
} }
alternate_descriptionFactory.Run(facade, config.zoom_level); alternate_descriptionFactory.Run(facade, config.zoom_level);
// //give an array of alternative routes // //give an array of alternative routes
reply.content.push_back("\"alternative_geometries\": ["); reply.content.push_back("\"alternative_geometries\": [");
if(config.geometry && INT_MAX != raw_route.lengthOfAlternativePath) { if (config.geometry && INVALID_EDGE_WEIGHT != raw_route.lengthOfAlternativePath)
//Generate the linestrings for each alternative {
alternate_descriptionFactory.AppendEncodedPolylineString( // Generate the linestrings for each alternative
config.encode_geometry, alternate_descriptionFactory.AppendEncodedPolylineString(config.encode_geometry,
reply.content reply.content);
);
} }
reply.content.push_back("],"); reply.content.push_back("],");
reply.content.push_back("\"alternative_instructions\":["); reply.content.push_back("\"alternative_instructions\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) { if (INVALID_EDGE_WEIGHT != raw_route.lengthOfAlternativePath)
{
reply.content.push_back("["); reply.content.push_back("[");
//Generate instructions for each alternative // Generate instructions for each alternative
if(config.instructions) { if (config.instructions)
BuildTextualDescription( {
alternate_descriptionFactory, BuildTextualDescription(alternate_descriptionFactory,
reply, reply,
raw_route.lengthOfAlternativePath, raw_route.lengthOfAlternativePath,
facade, facade,
alternative_path_segments alternative_path_segments);
);
} }
reply.content.push_back("]"); reply.content.push_back("]");
} }
reply.content.push_back("],"); reply.content.push_back("],");
reply.content.push_back("\"alternative_summaries\":["); reply.content.push_back("\"alternative_summaries\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) { if (INVALID_EDGE_WEIGHT != raw_route.lengthOfAlternativePath)
//Generate route summary (length, duration) for each alternative {
// Generate route summary (length, duration) for each alternative
alternate_descriptionFactory.BuildRouteSummary( alternate_descriptionFactory.BuildRouteSummary(
alternate_descriptionFactory.entireLength, alternate_descriptionFactory.entireLength, raw_route.lengthOfAlternativePath);
raw_route.lengthOfAlternativePath
);
reply.content.push_back("{"); reply.content.push_back("{");
reply.content.push_back("\"total_distance\":"); reply.content.push_back("\"total_distance\":");
reply.content.push_back( reply.content.push_back(alternate_descriptionFactory.summary.lengthString);
alternate_descriptionFactory.summary.lengthString
);
reply.content.push_back("," reply.content.push_back(","
"\"total_time\":"); "\"total_time\":");
reply.content.push_back( reply.content.push_back(alternate_descriptionFactory.summary.durationString);
alternate_descriptionFactory.summary.durationString
);
reply.content.push_back("," reply.content.push_back(","
"\"start_point\":\""); "\"start_point\":\"");
reply.content.push_back( reply.content.push_back(
facade->GetEscapedNameForNameID( facade->GetEscapedNameForNameID(description_factory.summary.startName));
description_factory.summary.startName
)
);
reply.content.push_back("\"," reply.content.push_back("\","
"\"end_point\":\""); "\"end_point\":\"");
reply.content.push_back(facade->GetEscapedNameForNameID(description_factory.summary.destName)); reply.content.push_back(
facade->GetEscapedNameForNameID(description_factory.summary.destName));
reply.content.push_back("\""); reply.content.push_back("\"");
reply.content.push_back("}"); reply.content.push_back("}");
} }
@ -295,37 +257,34 @@ public:
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames); GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
reply.content.push_back("\"route_name\":[\""); reply.content.push_back("\"route_name\":[\"");
reply.content.push_back(routeNames.shortestPathName1); reply.content.push_back(routeNames.shortest_path_name_1);
reply.content.push_back("\",\""); reply.content.push_back("\",\"");
reply.content.push_back(routeNames.shortestPathName2); reply.content.push_back(routeNames.shortest_path_name_2);
reply.content.push_back("\"]," reply.content.push_back("\"],"
"\"alternative_names\":["); "\"alternative_names\":[");
reply.content.push_back("[\""); reply.content.push_back("[\"");
reply.content.push_back(routeNames.alternativePathName1); reply.content.push_back(routeNames.alternative_path_name_1);
reply.content.push_back("\",\""); reply.content.push_back("\",\"");
reply.content.push_back(routeNames.alternativePathName2); reply.content.push_back(routeNames.alternative_path_name_2);
reply.content.push_back("\"]"); reply.content.push_back("\"]");
reply.content.push_back("],"); reply.content.push_back("],");
//list all viapoints so that the client may display it // list all viapoints so that the client may display it
reply.content.push_back("\"via_points\":["); reply.content.push_back("\"via_points\":[");
BOOST_ASSERT( !raw_route.segmentEndCoordinates.empty() ); BOOST_ASSERT(!raw_route.segmentEndCoordinates.empty());
std::string tmp; std::string tmp;
FixedPointCoordinate::convertInternalReversedCoordinateToString( FixedPointCoordinate::convertInternalReversedCoordinateToString(
raw_route.segmentEndCoordinates.front().source_phantom.location, raw_route.segmentEndCoordinates.front().source_phantom.location, tmp);
tmp
);
reply.content.push_back("["); reply.content.push_back("[");
reply.content.push_back(tmp); reply.content.push_back(tmp);
reply.content.push_back("]"); reply.content.push_back("]");
BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) { for (const PhantomNodes &nodes : raw_route.segmentEndCoordinates)
{
tmp.clear(); tmp.clear();
FixedPointCoordinate::convertInternalReversedCoordinateToString( FixedPointCoordinate::convertInternalReversedCoordinateToString(
nodes.target_phantom.location, nodes.target_phantom.location, tmp);
tmp
);
reply.content.push_back(",["); reply.content.push_back(",[");
reply.content.push_back(tmp); reply.content.push_back(tmp);
reply.content.push_back("]"); reply.content.push_back("]");
@ -333,19 +292,22 @@ public:
reply.content.push_back("],"); reply.content.push_back("],");
reply.content.push_back("\"via_indices\":["); reply.content.push_back("\"via_indices\":[");
BOOST_FOREACH(const unsigned index, shortest_leg_end_indices) { for (const unsigned index : shortest_leg_end_indices)
{
tmp.clear(); tmp.clear();
intToString(index, tmp); intToString(index, tmp);
reply.content.push_back(tmp); reply.content.push_back(tmp);
if( index != shortest_leg_end_indices.back() ) { if (index != shortest_leg_end_indices.back())
{
reply.content.push_back(","); reply.content.push_back(",");
} }
} }
reply.content.push_back("],\"alternative_indices\":["); reply.content.push_back("],\"alternative_indices\":[");
if(INT_MAX != raw_route.lengthOfAlternativePath) { if (INVALID_EDGE_WEIGHT != raw_route.lengthOfAlternativePath)
{
reply.content.push_back("0,"); reply.content.push_back("0,");
tmp.clear(); tmp.clear();
intToString(alternate_descriptionFactory.pathDescription.size(), tmp); intToString(alternate_descriptionFactory.path_description.size(), tmp);
reply.content.push_back(tmp); reply.content.push_back(tmp);
} }
@ -357,7 +319,8 @@ public:
reply.content.push_back(", \"locations\": ["); reply.content.push_back(", \"locations\": [");
std::string hint; std::string hint;
for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) { for (unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i)
{
reply.content.push_back("\""); reply.content.push_back("\"");
EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint); EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint);
reply.content.push_back(hint); reply.content.push_back(hint);
@ -371,91 +334,115 @@ public:
} }
// construct routes names // construct routes names
void GetRouteNames( void GetRouteNames(std::vector<Segment> &shortest_path_segments,
std::vector<Segment> & shortest_path_segments, std::vector<Segment> &alternative_path_segments,
std::vector<Segment> & alternative_path_segments, const DataFacadeT *facade,
const DataFacadeT * facade, RouteNames &routeNames)
RouteNames & routeNames {
) { Segment shortest_segment_1, shortest_segment_2;
Segment alternativeSegment1, alternative_segment_2;
Segment shortestSegment1, shortestSegment2; auto length_comperator = [](Segment a, Segment b)
Segment alternativeSegment1, alternativeSegment2; { return a.length < b.length; };
auto name_id_comperator = [](Segment a, Segment b)
{ return a.name_id < b.name_id; };
if(0 < shortest_path_segments.size()) { if (!shortest_path_segments.empty())
sort(shortest_path_segments.begin(), shortest_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) ); {
shortestSegment1 = shortest_path_segments[0]; std::sort(shortest_path_segments.begin(),
if(0 < alternative_path_segments.size()) { shortest_path_segments.end(),
sort(alternative_path_segments.begin(), alternative_path_segments.end(), boost::bind(&Segment::length, _1) > boost::bind(&Segment::length, _2) ); length_comperator);
shortest_segment_1 = shortest_path_segments[0];
if (!alternative_path_segments.empty())
{
std::sort(alternative_path_segments.begin(),
alternative_path_segments.end(),
length_comperator);
alternativeSegment1 = alternative_path_segments[0]; alternativeSegment1 = alternative_path_segments[0];
} }
std::vector<Segment> shortestDifference(shortest_path_segments.size()); std::vector<Segment> shortestDifference(shortest_path_segments.size());
std::vector<Segment> alternativeDifference(alternative_path_segments.size()); std::vector<Segment> alternativeDifference(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(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) ); std::set_difference(shortest_path_segments.begin(),
shortest_path_segments.end(),
alternative_path_segments.begin(),
alternative_path_segments.end(),
shortestDifference.begin(),
length_comperator);
int size_of_difference = shortestDifference.size(); int size_of_difference = shortestDifference.size();
if(0 < size_of_difference ) { if (size_of_difference)
{
int i = 0; int i = 0;
while( i < size_of_difference && shortestDifference[i].name_id == shortest_path_segments[0].name_id) { while (i < size_of_difference &&
shortestDifference[i].name_id == shortest_path_segments[0].name_id)
{
++i; ++i;
} }
if(i < size_of_difference ) { if (i < size_of_difference)
shortestSegment2 = shortestDifference[i]; {
shortest_segment_2 = shortestDifference[i];
} }
} }
std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), shortest_path_segments.begin(), shortest_path_segments.end(), alternativeDifference.begin(), boost::bind(&Segment::name_id, _1) < boost::bind(&Segment::name_id, _2) ); std::set_difference(alternative_path_segments.begin(),
alternative_path_segments.end(),
shortest_path_segments.begin(),
shortest_path_segments.end(),
alternativeDifference.begin(),
name_id_comperator);
size_of_difference = alternativeDifference.size(); size_of_difference = alternativeDifference.size();
if(0 < size_of_difference ) { if (size_of_difference)
{
int i = 0; int i = 0;
while( i < size_of_difference && alternativeDifference[i].name_id == alternative_path_segments[0].name_id) { while (i < size_of_difference &&
alternativeDifference[i].name_id == alternative_path_segments[0].name_id)
{
++i; ++i;
} }
if(i < size_of_difference ) { if (i < size_of_difference)
alternativeSegment2 = alternativeDifference[i]; {
alternative_segment_2 = alternativeDifference[i];
} }
} }
if(shortestSegment1.position > shortestSegment2.position) if (shortest_segment_1.position > shortest_segment_2.position)
std::swap(shortestSegment1, shortestSegment2); std::swap(shortest_segment_1, shortest_segment_2);
if(alternativeSegment1.position > alternativeSegment2.position) if (alternativeSegment1.position > alternative_segment_2.position)
std::swap(alternativeSegment1, alternativeSegment2); std::swap(alternativeSegment1, alternative_segment_2);
routeNames.shortestPathName1 = facade->GetEscapedNameForNameID( routeNames.shortest_path_name_1 =
shortestSegment1.name_id facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
); routeNames.shortest_path_name_2 =
routeNames.shortestPathName2 = facade->GetEscapedNameForNameID( facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
shortestSegment2.name_id
);
routeNames.alternativePathName1 = facade->GetEscapedNameForNameID( routeNames.alternative_path_name_1 =
alternativeSegment1.name_id facade->GetEscapedNameForNameID(alternativeSegment1.name_id);
); routeNames.alternative_path_name_2 =
routeNames.alternativePathName2 = facade->GetEscapedNameForNameID( facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
alternativeSegment2.name_id
);
} }
} }
//TODO: reorder parameters // TODO: reorder parameters
inline void BuildTextualDescription( inline void BuildTextualDescription(DescriptionFactory &description_factory,
DescriptionFactory & description_factory, http::Reply &reply,
http::Reply & reply, const int route_length,
const int route_length, const DataFacadeT *facade,
const DataFacadeT * facade, std::vector<Segment> &route_segments_list)
std::vector<Segment> & route_segments_list {
) { // 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]
unsigned necessary_segments_running_index = 0; unsigned necessary_segments_running_index = 0;
round_about.leave_at_exit = 0; round_about.leave_at_exit = 0;
round_about.name_id = 0; round_about.name_id = 0;
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction; std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
//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, description_factory.pathDescription) { for (const SegmentInformation &segment : description_factory.path_description)
TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag; {
TurnInstruction current_instruction =
segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
entered_restricted_area_count += (current_instruction != segment.turn_instruction); entered_restricted_area_count += (current_instruction != segment.turn_instruction);
if (TurnInstructionsClass::TurnIsNecessary( current_instruction) ) if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
{ {
if (TurnInstructionsClass::EnterRoundAbout == current_instruction) if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
{ {
@ -464,19 +451,22 @@ public:
} }
else else
{ {
if (0 != necessary_segments_running_index) if (necessary_segments_running_index)
{ {
reply.content.push_back(","); reply.content.push_back(",");
} }
reply.content.push_back("[\""); reply.content.push_back("[\"");
if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) { if (TurnInstructionsClass::LeaveRoundAbout == current_instruction)
{
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction); intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
reply.content.push_back(temp_instruction); reply.content.push_back(temp_instruction);
reply.content.push_back("-"); reply.content.push_back("-");
intToString(round_about.leave_at_exit+1, temp_instruction); intToString(round_about.leave_at_exit + 1, temp_instruction);
reply.content.push_back(temp_instruction); reply.content.push_back(temp_instruction);
round_about.leave_at_exit = 0; round_about.leave_at_exit = 0;
} else { }
else
{
intToString(current_instruction, temp_instruction); intToString(current_instruction, temp_instruction);
reply.content.push_back(temp_instruction); reply.content.push_back(temp_instruction);
} }
@ -490,13 +480,13 @@ public:
intToString(necessary_segments_running_index, temp_length); intToString(necessary_segments_running_index, temp_length);
reply.content.push_back(temp_length); reply.content.push_back(temp_length);
reply.content.push_back(","); reply.content.push_back(",");
intToString(round(segment.duration/10.), temp_duration); intToString(round(segment.duration / 10.), temp_duration);
reply.content.push_back(temp_duration); reply.content.push_back(temp_duration);
reply.content.push_back(",\""); reply.content.push_back(",\"");
intToString(segment.length, temp_length); intToString(segment.length, temp_length);
reply.content.push_back(temp_length); reply.content.push_back(temp_length);
reply.content.push_back("m\",\""); reply.content.push_back("m\",\"");
double bearing_value = round(segment.bearing/10.); int bearing_value = round(segment.bearing / 10.);
reply.content.push_back(Azimuth::Get(bearing_value)); reply.content.push_back(Azimuth::Get(bearing_value));
reply.content.push_back("\","); reply.content.push_back("\",");
intToString(bearing_value, temp_bearing); intToString(bearing_value, temp_bearing);
@ -504,20 +494,20 @@ public:
reply.content.push_back("]"); reply.content.push_back("]");
route_segments_list.push_back( route_segments_list.push_back(
Segment( Segment(segment.name_id, segment.length, route_segments_list.size()));
segment.name_id,
segment.length,
route_segments_list.size()
)
);
} }
} else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) { }
else if (TurnInstructionsClass::StayOnRoundAbout == current_instruction)
{
++round_about.leave_at_exit; ++round_about.leave_at_exit;
} }
if(segment.necessary) if (segment.necessary)
{
++necessary_segments_running_index; ++necessary_segments_running_index;
}
} }
if(INT_MAX != route_length) { if (INVALID_EDGE_WEIGHT != route_length)
{
reply.content.push_back(",[\""); reply.content.push_back(",[\"");
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction); intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
reply.content.push_back(temp_instruction); reply.content.push_back(temp_instruction);
@ -525,7 +515,7 @@ public:
reply.content.push_back("\","); reply.content.push_back("\",");
reply.content.push_back("0"); reply.content.push_back("0");
reply.content.push_back(","); reply.content.push_back(",");
intToString(necessary_segments_running_index-1, temp_length); intToString(necessary_segments_running_index - 1, temp_length);
reply.content.push_back(temp_length); reply.content.push_back(temp_length);
reply.content.push_back(","); reply.content.push_back(",");
reply.content.push_back("0"); reply.content.push_back("0");