use JSON container to hold all intermediate results:
- no hand-rolled GPX generation anymore - render gpx thru a JSONContainer visitor pattern - precursor to expose JSON containter as result from OSRM lib interface, cf. #1261
This commit is contained in:
parent
c581563230
commit
6859b53155
@ -29,31 +29,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#define GPX_DESCRIPTOR_H
|
#define GPX_DESCRIPTOR_H
|
||||||
|
|
||||||
#include "BaseDescriptor.h"
|
#include "BaseDescriptor.h"
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
#include "../Util/xml_renderer.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
|
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DescriptorConfig config;
|
DescriptorConfig config;
|
||||||
FixedPointCoordinate current;
|
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
|
|
||||||
void AddRoutePoint(const FixedPointCoordinate &coordinate, std::vector<char> &output)
|
void AddRoutePoint(const FixedPointCoordinate &coordinate, JSON::Array &json_result)
|
||||||
{
|
{
|
||||||
const std::string route_point_head = "<rtept lat=\"";
|
JSON::Object json_lat;
|
||||||
const std::string route_point_middle = " lon=\"";
|
JSON::Object json_lon;
|
||||||
const std::string route_point_tail = "\"></rtept>";
|
JSON::Array json_row;
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||||
output.insert(output.end(), route_point_head.begin(), route_point_head.end());
|
json_lat.values["_lat"] = tmp;
|
||||||
output.insert(output.end(), tmp.begin(), tmp.end());
|
|
||||||
output.push_back('\"');
|
|
||||||
|
|
||||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||||
output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
|
json_lon.values["_lon"] = tmp;
|
||||||
output.insert(output.end(), tmp.begin(), tmp.end());
|
|
||||||
output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
|
json_row.values.push_back(json_lat);
|
||||||
|
json_row.values.push_back(json_lon);
|
||||||
|
JSON::Object entry;
|
||||||
|
entry.values["rtept"] = json_row;
|
||||||
|
json_result.values.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -61,26 +66,13 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
|||||||
|
|
||||||
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||||
|
|
||||||
// TODO: reorder parameters
|
|
||||||
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||||
{
|
{
|
||||||
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
JSON::Array json_result;
|
||||||
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT)
|
||||||
"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)
|
|
||||||
{
|
{
|
||||||
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
|
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
|
||||||
reply.content);
|
json_result);
|
||||||
|
|
||||||
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||||
{
|
{
|
||||||
@ -88,14 +80,13 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
|||||||
{
|
{
|
||||||
const FixedPointCoordinate current_coordinate =
|
const FixedPointCoordinate current_coordinate =
|
||||||
facade->GetCoordinateOfNode(path_data.node);
|
facade->GetCoordinateOfNode(path_data.node);
|
||||||
AddRoutePoint(current_coordinate, reply.content);
|
AddRoutePoint(current_coordinate, json_result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
||||||
reply.content);
|
json_result);
|
||||||
}
|
}
|
||||||
std::string footer("</rte></gpx>");
|
JSON::gpx_render(reply.content, json_result);
|
||||||
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif // GPX_DESCRIPTOR_H
|
#endif // GPX_DESCRIPTOR_H
|
||||||
|
140
Util/xml_renderer.hpp
Normal file
140
Util/xml_renderer.hpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XML_RENDERER_HPP
|
||||||
|
#define XML_RENDERER_HPP
|
||||||
|
|
||||||
|
#include "../DataStructures/JSONContainer.h"
|
||||||
|
#include "cast.hpp"
|
||||||
|
|
||||||
|
namespace JSON {
|
||||||
|
|
||||||
|
struct XMLToArrayRenderer : mapbox::util::static_visitor<>
|
||||||
|
{
|
||||||
|
explicit XMLToArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||||
|
|
||||||
|
void operator()(const String &string) const
|
||||||
|
{
|
||||||
|
out.push_back('\"');
|
||||||
|
out.insert(out.end(), string.value.begin(), string.value.end());
|
||||||
|
out.push_back('\"');
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Number &number) const
|
||||||
|
{
|
||||||
|
const std::string number_string = cast::double_fixed_to_string(number.value);
|
||||||
|
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Object &object) const
|
||||||
|
{
|
||||||
|
auto iterator = object.values.begin();
|
||||||
|
while (iterator != object.values.end())
|
||||||
|
{
|
||||||
|
if (iterator->first.at(0) != '_')
|
||||||
|
{
|
||||||
|
out.push_back('<');
|
||||||
|
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.push_back(' ');
|
||||||
|
out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end());
|
||||||
|
out.push_back('=');
|
||||||
|
|
||||||
|
}
|
||||||
|
mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second);
|
||||||
|
if (iterator->first.at(0) != '_')
|
||||||
|
{
|
||||||
|
out.push_back('/');
|
||||||
|
out.push_back('>');
|
||||||
|
}
|
||||||
|
++iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Array &array) const
|
||||||
|
{
|
||||||
|
std::vector<Value>::const_iterator iterator;
|
||||||
|
iterator = array.values.begin();
|
||||||
|
while (iterator != array.values.end())
|
||||||
|
{
|
||||||
|
mapbox::util::apply_visitor(XMLToArrayRenderer(out), *iterator);
|
||||||
|
++iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const True &) const
|
||||||
|
{
|
||||||
|
const std::string temp("true");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const False &) const
|
||||||
|
{
|
||||||
|
const std::string temp("false");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(const Null &) const
|
||||||
|
{
|
||||||
|
const std::string temp("null");
|
||||||
|
out.insert(out.end(), temp.begin(), temp.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<char> &out;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class JSONObject>
|
||||||
|
inline void xml_render(std::vector<char> &out, const JSONObject &object)
|
||||||
|
{
|
||||||
|
Value value = object;
|
||||||
|
mapbox::util::apply_visitor(XMLToArrayRenderer(out), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class JSONObject>
|
||||||
|
inline void gpx_render(std::vector<char> &out, const JSONObject &object)
|
||||||
|
{
|
||||||
|
// add header
|
||||||
|
|
||||||
|
const 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.topogr"
|
||||||
|
"afix.com/GPX/1/1 gpx.xsd\"><metadata><copyright author=\"Project OSRM\"><lice"
|
||||||
|
"nse>Data (c) OpenStreetMap contributors (ODbL)</license></copyright></metadat"
|
||||||
|
"a><rte>"};
|
||||||
|
out.insert(out.end(), header.begin(), header.end());
|
||||||
|
|
||||||
|
xml_render(out, object);
|
||||||
|
|
||||||
|
const std::string footer {"</rte></gpx>"};
|
||||||
|
out.insert(out.end(), footer.begin(), footer.end());
|
||||||
|
}
|
||||||
|
} // namespace JSON
|
||||||
|
|
||||||
|
#endif // XML_RENDERER_HPP
|
Loading…
Reference in New Issue
Block a user