2011-11-17 12:56:45 -05:00
|
|
|
/*
|
2013-10-14 07:42:28 -04:00
|
|
|
|
|
|
|
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
|
|
are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
Redistributions of source code must retain the above copyright notice, this list
|
|
|
|
of conditions and the following disclaimer.
|
|
|
|
Redistributions in binary form must reproduce the above copyright notice, this
|
|
|
|
list of conditions and the following disclaimer in the documentation and/or
|
|
|
|
other materials provided with the distribution.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
|
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
*/
|
2011-11-17 12:56:45 -05:00
|
|
|
|
|
|
|
#ifndef JSON_DESCRIPTOR_H_
|
|
|
|
#define JSON_DESCRIPTOR_H_
|
|
|
|
|
|
|
|
#include "BaseDescriptor.h"
|
|
|
|
#include "DescriptionFactory.h"
|
2012-03-05 09:44:21 -05:00
|
|
|
#include "../Algorithms/ObjectToBase64.h"
|
2011-11-17 12:56:45 -05:00
|
|
|
#include "../DataStructures/SegmentInformation.h"
|
|
|
|
#include "../DataStructures/TurnInstructions.h"
|
2012-02-07 08:47:01 -05:00
|
|
|
#include "../Util/Azimuth.h"
|
2011-11-17 12:56:45 -05:00
|
|
|
#include "../Util/StringUtil.h"
|
|
|
|
|
2013-06-26 19:48:22 -04:00
|
|
|
#include <algorithm>
|
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
|
|
|
|
{
|
|
|
|
private:
|
2014-03-26 10:14:39 -04:00
|
|
|
// TODO: initalize in c'tor
|
2014-05-02 13:07:55 -04:00
|
|
|
DataFacadeT *facade;
|
2013-09-19 16:10:49 -04:00
|
|
|
DescriptorConfig config;
|
2013-09-19 13:07:18 -04:00
|
|
|
DescriptionFactory description_factory;
|
2013-12-12 18:35:23 -05:00
|
|
|
DescriptionFactory alternate_descriptionFactory;
|
2013-08-14 07:12:28 -04:00
|
|
|
FixedPointCoordinate current;
|
2013-09-19 13:07:18 -04:00
|
|
|
unsigned entered_restricted_area_count;
|
2014-05-02 13:07:55 -04:00
|
|
|
struct RoundAbout
|
|
|
|
{
|
|
|
|
RoundAbout() : start_index(INT_MAX), name_id(INT_MAX), leave_at_exit(INT_MAX) {}
|
2013-09-19 13:07:18 -04:00
|
|
|
int start_index;
|
|
|
|
int name_id;
|
|
|
|
int leave_at_exit;
|
2014-03-26 10:14:39 -04:00
|
|
|
} round_about;
|
2011-11-17 12:56:45 -05:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
struct Segment
|
|
|
|
{
|
2013-09-19 13:07:18 -04:00
|
|
|
Segment() : name_id(-1), length(-1), position(-1) {}
|
|
|
|
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
|
|
|
int name_id;
|
2012-09-13 05:32:07 -04:00
|
|
|
int length;
|
|
|
|
int position;
|
|
|
|
};
|
2013-09-19 13:07:18 -04:00
|
|
|
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
2013-12-12 18:35:23 -05:00
|
|
|
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
2012-09-13 05:32:07 -04:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
struct RouteNames
|
|
|
|
{
|
|
|
|
std::string shortest_path_name_1;
|
|
|
|
std::string shortest_path_name_2;
|
|
|
|
std::string alternative_path_name_1;
|
|
|
|
std::string alternative_path_name_2;
|
2012-09-13 05:32:07 -04:00
|
|
|
};
|
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
public:
|
|
|
|
JSONDescriptor() : facade(nullptr), entered_restricted_area_count(0)
|
2013-12-13 09:52:57 -05:00
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
shortest_leg_end_indices.push_back(0);
|
|
|
|
alternative_leg_end_indices.push_back(0);
|
|
|
|
}
|
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
void SetConfig(const DescriptorConfig &c) { config = c; }
|
2012-03-23 12:44:56 -04:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
|
|
|
|
{
|
|
|
|
unsigned added_element_count = 0;
|
|
|
|
// Get all the coordinates for the computed route
|
2013-12-12 18:35:23 -05:00
|
|
|
FixedPointCoordinate current_coordinate;
|
2014-05-02 13:07:55 -04:00
|
|
|
for (const PathData &path_data : route_leg)
|
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
2014-03-28 12:13:00 -04:00
|
|
|
description_factory.AppendSegment(current_coordinate, path_data);
|
2013-12-12 18:35:23 -05:00
|
|
|
++added_element_count;
|
|
|
|
}
|
2014-03-25 13:06:05 -04:00
|
|
|
// description_factory.SetEndSegment( leg_phantoms.target_phantom );
|
2013-12-12 18:35:23 -05:00
|
|
|
++added_element_count;
|
2014-05-02 13:07:55 -04:00
|
|
|
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
2013-12-12 18:35:23 -05:00
|
|
|
return added_element_count;
|
|
|
|
}
|
2012-12-17 07:14:43 -05:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
void Run(const RawRouteData &raw_route,
|
|
|
|
const PhantomNodes &phantom_nodes,
|
|
|
|
// TODO: move facade initalization to c'tor
|
|
|
|
DataFacadeT *f,
|
|
|
|
http::Reply &reply)
|
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
facade = f;
|
2014-05-02 13:07:55 -04:00
|
|
|
reply.content.push_back("{\"status\":");
|
2012-12-17 07:14:43 -05:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
2014-03-28 12:13:00 -04:00
|
|
|
{
|
2014-05-02 13:07:55 -04:00
|
|
|
// We do not need to do much, if there is no route ;-)
|
2013-12-27 06:38:08 -05:00
|
|
|
reply.content.push_back(
|
2014-05-02 13:07:55 -04:00
|
|
|
"207,\"status_message\": \"Cannot find route between points\"}");
|
2013-12-12 18:35:23 -05:00
|
|
|
return;
|
2012-03-23 12:44:56 -04:00
|
|
|
}
|
2011-11-17 12:56:45 -05:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.shortest_path_length;
|
2014-04-25 07:22:58 -04:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
// check if first segment is non-zero
|
|
|
|
std::string road_name =
|
|
|
|
facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
2014-03-28 12:13:00 -04:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
2014-05-07 12:39:16 -04:00
|
|
|
raw_route.segment_end_coordinates.size());
|
2014-03-28 12:13:00 -04:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
description_factory.SetStartSegment(phantom_nodes.source_phantom,
|
|
|
|
raw_route.source_traversed_in_reverse);
|
2013-12-27 06:38:08 -05:00
|
|
|
reply.content.push_back("0,"
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"status_message\": \"Found route between points\",");
|
2013-12-27 06:38:08 -05:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
// for each unpacked segment add the leg to the description
|
2014-03-28 12:13:00 -04:00
|
|
|
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
|
|
|
{
|
2014-05-02 13:07:55 -04:00
|
|
|
const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
|
2014-05-07 12:39:16 -04:00
|
|
|
raw_route.segment_end_coordinates[i]);
|
2014-05-02 13:07:55 -04:00
|
|
|
BOOST_ASSERT(0 < added_segments);
|
|
|
|
shortest_leg_end_indices.push_back(added_segments + shortest_leg_end_indices.back());
|
2013-12-27 06:38:08 -05:00
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
description_factory.SetEndSegment(phantom_nodes.target_phantom,
|
|
|
|
raw_route.target_traversed_in_reverse);
|
2013-12-27 06:38:08 -05:00
|
|
|
description_factory.Run(facade, config.zoom_level);
|
|
|
|
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"route_geometry\": ");
|
2014-05-02 13:07:55 -04:00
|
|
|
if (config.geometry)
|
|
|
|
{
|
|
|
|
description_factory.AppendEncodedPolylineString(config.encode_geometry, reply.content);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("[]");
|
2012-03-23 12:44:56 -04:00
|
|
|
}
|
|
|
|
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back(",\"route_instructions\": [");
|
2014-05-02 13:07:55 -04:00
|
|
|
if (config.instructions)
|
|
|
|
{
|
|
|
|
BuildTextualDescription(description_factory,
|
|
|
|
reply,
|
2014-05-07 12:39:16 -04:00
|
|
|
raw_route.shortest_path_length,
|
2014-05-02 13:07:55 -04:00
|
|
|
facade,
|
|
|
|
shortest_path_segments);
|
2012-03-23 12:44:56 -04:00
|
|
|
}
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("],");
|
2014-05-02 13:07:55 -04:00
|
|
|
description_factory.BuildRouteSummary(description_factory.entireLength,
|
2014-05-07 12:39:16 -04:00
|
|
|
raw_route.shortest_path_length);
|
2012-03-23 12:44:56 -04:00
|
|
|
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"route_summary\":");
|
|
|
|
reply.content.push_back("{");
|
|
|
|
reply.content.push_back("\"total_distance\":");
|
|
|
|
reply.content.push_back(description_factory.summary.lengthString);
|
|
|
|
reply.content.push_back(","
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"total_time\":");
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(description_factory.summary.durationString);
|
|
|
|
reply.content.push_back(","
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"start_point\":\"");
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(
|
2014-05-02 13:07:55 -04:00
|
|
|
facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\","
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"end_point\":\"");
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(
|
2014-05-02 13:07:55 -04:00
|
|
|
facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"");
|
|
|
|
reply.content.push_back("}");
|
|
|
|
reply.content.push_back(",");
|
2012-06-19 11:26:34 -04:00
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
// only one alternative route is computed at this time, so this is hardcoded
|
2014-05-07 12:39:16 -04:00
|
|
|
if (raw_route.alternative_path_length != INVALID_EDGE_WEIGHT)
|
2014-03-28 12:13:00 -04:00
|
|
|
{
|
2014-05-02 13:07:55 -04:00
|
|
|
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom,
|
|
|
|
raw_route.alt_source_traversed_in_reverse);
|
|
|
|
// Get all the coordinates for the computed route
|
|
|
|
for (const PathData &path_data : raw_route.unpacked_alternative)
|
|
|
|
{
|
2013-09-19 13:07:18 -04:00
|
|
|
current = facade->GetCoordinateOfNode(path_data.node);
|
2014-05-02 13:07:55 -04:00
|
|
|
alternate_descriptionFactory.AppendSegment(current, path_data);
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom,
|
|
|
|
raw_route.alt_target_traversed_in_reverse);
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2013-12-12 18:35:23 -05:00
|
|
|
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
2012-06-19 11:26:34 -04:00
|
|
|
|
2013-12-12 18:35:23 -05:00
|
|
|
// //give an array of alternative routes
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"alternative_geometries\": [");
|
2014-05-07 12:39:16 -04:00
|
|
|
if (config.geometry && INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
2014-05-02 13:07:55 -04:00
|
|
|
{
|
|
|
|
// Generate the linestrings for each alternative
|
|
|
|
alternate_descriptionFactory.AppendEncodedPolylineString(config.encode_geometry,
|
|
|
|
reply.content);
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("],");
|
|
|
|
reply.content.push_back("\"alternative_instructions\":[");
|
2014-05-07 12:39:16 -04:00
|
|
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
2014-05-02 13:07:55 -04:00
|
|
|
{
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("[");
|
2014-05-02 13:07:55 -04:00
|
|
|
// Generate instructions for each alternative
|
|
|
|
if (config.instructions)
|
|
|
|
{
|
|
|
|
BuildTextualDescription(alternate_descriptionFactory,
|
|
|
|
reply,
|
2014-05-07 12:39:16 -04:00
|
|
|
raw_route.alternative_path_length,
|
2014-05-02 13:07:55 -04:00
|
|
|
facade,
|
|
|
|
alternative_path_segments);
|
2012-07-11 04:44:11 -04:00
|
|
|
}
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("]");
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("],");
|
|
|
|
reply.content.push_back("\"alternative_summaries\":[");
|
2014-05-07 12:39:16 -04:00
|
|
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
2014-05-02 13:07:55 -04:00
|
|
|
{
|
|
|
|
// Generate route summary (length, duration) for each alternative
|
2013-12-12 18:35:23 -05:00
|
|
|
alternate_descriptionFactory.BuildRouteSummary(
|
2014-05-07 12:39:16 -04:00
|
|
|
alternate_descriptionFactory.entireLength, raw_route.alternative_path_length);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("{");
|
|
|
|
reply.content.push_back("\"total_distance\":");
|
2014-05-02 13:07:55 -04:00
|
|
|
reply.content.push_back(alternate_descriptionFactory.summary.lengthString);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(","
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"total_time\":");
|
|
|
|
reply.content.push_back(alternate_descriptionFactory.summary.durationString);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(","
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"start_point\":\"");
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back(
|
2014-05-02 13:07:55 -04:00
|
|
|
facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\","
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"end_point\":\"");
|
|
|
|
reply.content.push_back(
|
|
|
|
facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"");
|
|
|
|
reply.content.push_back("}");
|
2012-06-21 06:26:46 -04:00
|
|
|
}
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("],");
|
2012-03-23 12:44:56 -04:00
|
|
|
|
2013-12-12 18:35:23 -05:00
|
|
|
// //Get Names for both routes
|
2012-09-13 05:32:07 -04:00
|
|
|
RouteNames routeNames;
|
2013-09-19 13:07:18 -04:00
|
|
|
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
2012-09-13 05:32:07 -04:00
|
|
|
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"route_name\":[\"");
|
2014-05-02 13:07:55 -04:00
|
|
|
reply.content.push_back(routeNames.shortest_path_name_1);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\",\"");
|
2014-05-02 13:07:55 -04:00
|
|
|
reply.content.push_back(routeNames.shortest_path_name_2);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"],"
|
2014-05-02 13:07:55 -04:00
|
|
|
"\"alternative_names\":[");
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("[\"");
|
2014-05-02 13:07:55 -04:00
|
|
|
reply.content.push_back(routeNames.alternative_path_name_1);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\",\"");
|
2014-05-02 13:07:55 -04:00
|
|
|
reply.content.push_back(routeNames.alternative_path_name_2);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"]");
|
|
|
|
reply.content.push_back("],");
|
2014-05-02 13:07:55 -04:00
|
|
|
// list all viapoints so that the client may display it
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"via_points\":[");
|
2013-12-12 18:35:23 -05:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
2013-12-12 18:35:23 -05:00
|
|
|
|
2012-02-17 02:34:52 -05:00
|
|
|
std::string tmp;
|
2013-12-13 17:26:57 -05:00
|
|
|
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
2014-05-07 12:39:16 -04:00
|
|
|
raw_route.segment_end_coordinates.front().source_phantom.location, tmp);
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back("[");
|
|
|
|
reply.content.push_back(tmp);
|
|
|
|
reply.content.push_back("]");
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
2014-05-02 13:07:55 -04:00
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
tmp.clear();
|
2013-12-13 17:26:57 -05:00
|
|
|
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
2014-05-02 13:07:55 -04:00
|
|
|
nodes.target_phantom.location, tmp);
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back(",[");
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(tmp);
|
|
|
|
reply.content.push_back("]");
|
2012-03-23 12:44:56 -04:00
|
|
|
}
|
2013-12-12 18:35:23 -05:00
|
|
|
|
|
|
|
reply.content.push_back("],");
|
|
|
|
reply.content.push_back("\"via_indices\":[");
|
2014-05-02 13:07:55 -04:00
|
|
|
for (const unsigned index : shortest_leg_end_indices)
|
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
tmp.clear();
|
|
|
|
intToString(index, tmp);
|
|
|
|
reply.content.push_back(tmp);
|
2014-05-02 13:07:55 -04:00
|
|
|
if (index != shortest_leg_end_indices.back())
|
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back(",");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reply.content.push_back("],\"alternative_indices\":[");
|
2014-05-07 12:39:16 -04:00
|
|
|
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
2014-05-02 13:07:55 -04:00
|
|
|
{
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back("0,");
|
|
|
|
tmp.clear();
|
2014-05-02 13:07:55 -04:00
|
|
|
intToString(alternate_descriptionFactory.path_description.size(), tmp);
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back(tmp);
|
|
|
|
}
|
|
|
|
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("],");
|
|
|
|
reply.content.push_back("\"hint_data\": {");
|
|
|
|
reply.content.push_back("\"checksum\":");
|
2014-05-07 12:39:16 -04:00
|
|
|
intToString(raw_route.check_sum, tmp);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(tmp);
|
|
|
|
reply.content.push_back(", \"locations\": [");
|
2012-02-17 10:27:54 -05:00
|
|
|
|
2012-05-15 10:42:31 -04:00
|
|
|
std::string hint;
|
2014-05-07 12:39:16 -04:00
|
|
|
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
|
2014-05-02 13:07:55 -04:00
|
|
|
{
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"");
|
2014-05-07 12:39:16 -04:00
|
|
|
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(hint);
|
|
|
|
reply.content.push_back("\", ");
|
2012-02-17 10:27:54 -05:00
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\"");
|
|
|
|
reply.content.push_back(hint);
|
|
|
|
reply.content.push_back("\"]");
|
2013-12-12 18:35:23 -05:00
|
|
|
reply.content.push_back("}}");
|
2012-09-13 05:32:07 -04:00
|
|
|
}
|
|
|
|
|
2013-09-19 12:54:30 -04:00
|
|
|
// construct routes names
|
2014-05-02 13:07:55 -04:00
|
|
|
void GetRouteNames(std::vector<Segment> &shortest_path_segments,
|
|
|
|
std::vector<Segment> &alternative_path_segments,
|
|
|
|
const DataFacadeT *facade,
|
|
|
|
RouteNames &routeNames)
|
|
|
|
{
|
|
|
|
Segment shortest_segment_1, shortest_segment_2;
|
|
|
|
Segment alternativeSegment1, alternative_segment_2;
|
|
|
|
|
|
|
|
auto length_comperator = [](Segment a, Segment b)
|
|
|
|
{ return a.length < b.length; };
|
|
|
|
auto name_id_comperator = [](Segment a, Segment b)
|
|
|
|
{ return a.name_id < b.name_id; };
|
|
|
|
|
|
|
|
if (!shortest_path_segments.empty())
|
|
|
|
{
|
|
|
|
std::sort(shortest_path_segments.begin(),
|
|
|
|
shortest_path_segments.end(),
|
|
|
|
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);
|
2013-09-19 13:07:18 -04:00
|
|
|
alternativeSegment1 = alternative_path_segments[0];
|
2012-09-13 05:32:07 -04:00
|
|
|
}
|
2013-09-19 13:07:18 -04:00
|
|
|
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
|
|
|
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
2014-05-02 13:07:55 -04:00
|
|
|
std::set_difference(shortest_path_segments.begin(),
|
|
|
|
shortest_path_segments.end(),
|
|
|
|
alternative_path_segments.begin(),
|
|
|
|
alternative_path_segments.end(),
|
|
|
|
shortestDifference.begin(),
|
|
|
|
length_comperator);
|
2013-01-06 06:39:12 -05:00
|
|
|
int size_of_difference = shortestDifference.size();
|
2014-05-02 13:07:55 -04:00
|
|
|
if (size_of_difference)
|
|
|
|
{
|
2013-02-03 11:07:31 -05:00
|
|
|
int i = 0;
|
2014-05-02 13:07:55 -04:00
|
|
|
while (i < size_of_difference &&
|
|
|
|
shortestDifference[i].name_id == shortest_path_segments[0].name_id)
|
|
|
|
{
|
2012-09-13 05:32:07 -04:00
|
|
|
++i;
|
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
if (i < size_of_difference)
|
|
|
|
{
|
|
|
|
shortest_segment_2 = shortestDifference[i];
|
2012-09-13 05:32:07 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
std::set_difference(alternative_path_segments.begin(),
|
|
|
|
alternative_path_segments.end(),
|
|
|
|
shortest_path_segments.begin(),
|
|
|
|
shortest_path_segments.end(),
|
|
|
|
alternativeDifference.begin(),
|
|
|
|
name_id_comperator);
|
2013-01-06 06:39:12 -05:00
|
|
|
size_of_difference = alternativeDifference.size();
|
2014-05-02 13:07:55 -04:00
|
|
|
if (size_of_difference)
|
|
|
|
{
|
2013-02-03 11:07:31 -05:00
|
|
|
int i = 0;
|
2014-05-02 13:07:55 -04:00
|
|
|
while (i < size_of_difference &&
|
|
|
|
alternativeDifference[i].name_id == alternative_path_segments[0].name_id)
|
|
|
|
{
|
2012-09-13 05:32:07 -04:00
|
|
|
++i;
|
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
if (i < size_of_difference)
|
|
|
|
{
|
|
|
|
alternative_segment_2 = alternativeDifference[i];
|
2012-09-13 05:32:07 -04:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
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 =
|
|
|
|
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
|
|
|
routeNames.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 =
|
|
|
|
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
|
2012-09-13 05:32:07 -04:00
|
|
|
}
|
2012-03-23 12:44:56 -04:00
|
|
|
}
|
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
// TODO: reorder parameters
|
|
|
|
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
|
|
|
http::Reply &reply,
|
|
|
|
const int route_length,
|
|
|
|
const DataFacadeT *facade,
|
|
|
|
std::vector<Segment> &route_segments_list)
|
|
|
|
{
|
|
|
|
// Segment information has following format:
|
2012-06-19 11:26:34 -04:00
|
|
|
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
2014-05-02 13:07:55 -04:00
|
|
|
// Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
2014-03-26 10:14:39 -04:00
|
|
|
unsigned necessary_segments_running_index = 0;
|
|
|
|
round_about.leave_at_exit = 0;
|
|
|
|
round_about.name_id = 0;
|
|
|
|
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
|
|
|
|
2014-05-02 13:07:55 -04:00
|
|
|
// Fetch data from Factory and generate a string from it.
|
|
|
|
for (const SegmentInformation &segment : description_factory.path_description)
|
|
|
|
{
|
|
|
|
TurnInstruction current_instruction =
|
|
|
|
segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag;
|
2013-12-08 12:33:53 -05:00
|
|
|
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
2014-05-02 13:07:55 -04:00
|
|
|
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
2014-03-26 10:14:39 -04:00
|
|
|
{
|
|
|
|
if (TurnInstructionsClass::EnterRoundAbout == current_instruction)
|
|
|
|
{
|
|
|
|
round_about.name_id = segment.name_id;
|
|
|
|
round_about.start_index = necessary_segments_running_index;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-02 13:07:55 -04:00
|
|
|
if (necessary_segments_running_index)
|
2014-03-26 10:14:39 -04:00
|
|
|
{
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(",");
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("[\"");
|
2014-05-02 13:07:55 -04:00
|
|
|
if (TurnInstructionsClass::LeaveRoundAbout == current_instruction)
|
|
|
|
{
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction);
|
|
|
|
reply.content.push_back(temp_instruction);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("-");
|
2014-05-02 13:07:55 -04:00
|
|
|
intToString(round_about.leave_at_exit + 1, temp_instruction);
|
2014-03-26 10:14:39 -04:00
|
|
|
reply.content.push_back(temp_instruction);
|
|
|
|
round_about.leave_at_exit = 0;
|
2014-05-02 13:07:55 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(current_instruction, temp_instruction);
|
|
|
|
reply.content.push_back(temp_instruction);
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2012-09-13 05:32:07 -04:00
|
|
|
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\",\"");
|
2013-12-08 12:33:53 -05:00
|
|
|
reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\",");
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(segment.length, temp_dist);
|
|
|
|
reply.content.push_back(temp_dist);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(",");
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(necessary_segments_running_index, temp_length);
|
|
|
|
reply.content.push_back(temp_length);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(",");
|
2014-05-02 13:07:55 -04:00
|
|
|
intToString(round(segment.duration / 10.), temp_duration);
|
2014-03-26 10:14:39 -04:00
|
|
|
reply.content.push_back(temp_duration);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(",\"");
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(segment.length, temp_length);
|
|
|
|
reply.content.push_back(temp_length);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("m\",\"");
|
2014-05-02 13:07:55 -04:00
|
|
|
int bearing_value = round(segment.bearing / 10.);
|
2013-12-08 12:33:53 -05:00
|
|
|
reply.content.push_back(Azimuth::Get(bearing_value));
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\",");
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(bearing_value, temp_bearing);
|
|
|
|
reply.content.push_back(temp_bearing);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("]");
|
2012-09-13 05:32:07 -04:00
|
|
|
|
2013-09-19 13:07:18 -04:00
|
|
|
route_segments_list.push_back(
|
2014-05-02 13:07:55 -04:00
|
|
|
Segment(segment.name_id, segment.length, route_segments_list.size()));
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
}
|
|
|
|
else if (TurnInstructionsClass::StayOnRoundAbout == current_instruction)
|
|
|
|
{
|
2014-03-26 10:14:39 -04:00
|
|
|
++round_about.leave_at_exit;
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
if (segment.necessary)
|
|
|
|
{
|
2014-03-26 10:14:39 -04:00
|
|
|
++necessary_segments_running_index;
|
2014-05-02 13:07:55 -04:00
|
|
|
}
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
2014-05-02 13:07:55 -04:00
|
|
|
if (INVALID_EDGE_WEIGHT != route_length)
|
|
|
|
{
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(",[\"");
|
2014-03-26 10:14:39 -04:00
|
|
|
intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction);
|
|
|
|
reply.content.push_back(temp_instruction);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back("\",\"");
|
|
|
|
reply.content.push_back("\",");
|
|
|
|
reply.content.push_back("0");
|
|
|
|
reply.content.push_back(",");
|
2014-05-02 13:07:55 -04:00
|
|
|
intToString(necessary_segments_running_index - 1, temp_length);
|
2014-03-26 10:14:39 -04:00
|
|
|
reply.content.push_back(temp_length);
|
2013-11-14 17:16:26 -05:00
|
|
|
reply.content.push_back(",");
|
|
|
|
reply.content.push_back("0");
|
|
|
|
reply.content.push_back(",\"");
|
|
|
|
reply.content.push_back("\",\"");
|
|
|
|
reply.content.push_back(Azimuth::Get(0.0));
|
|
|
|
reply.content.push_back("\",");
|
|
|
|
reply.content.push_back("0.0");
|
|
|
|
reply.content.push_back("]");
|
2012-06-19 11:26:34 -04:00
|
|
|
}
|
|
|
|
}
|
2011-11-17 12:56:45 -05:00
|
|
|
};
|
2014-04-03 13:45:00 -04:00
|
|
|
|
2011-11-17 12:56:45 -05:00
|
|
|
#endif /* JSON_DESCRIPTOR_H_ */
|