Merge pull request #1292 from Project-OSRM/feature/json_lib_interface
Feature/json lib interface
This commit is contained in:
commit
e296264ea6
@ -71,7 +71,7 @@ file(GLOB ServerGlob Server/*.cpp)
|
||||
file(GLOB DescriptorGlob descriptors/*.cpp)
|
||||
file(GLOB DatastructureGlob data_structures/search_engine_data.cpp data_structures/route_parameters.cpp Util/bearing.cpp)
|
||||
list(REMOVE_ITEM DatastructureGlob data_structures/Coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/Coordinate.cpp)
|
||||
file(GLOB CoordinateGlob data_structures/coordinate.cpp)
|
||||
file(GLOB AlgorithmGlob algorithms/*.cpp)
|
||||
file(GLOB HttpGlob Server/Http/*.cpp)
|
||||
file(GLOB LibOSRMGlob Library/*.cpp)
|
||||
@ -299,7 +299,7 @@ if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
else()
|
||||
message(FATAL_ERROR "libgdal and/or development headers not found")
|
||||
endif()
|
||||
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||
add_executable(osrm-cli tools/simpleclient.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:COORDINATE>)
|
||||
target_link_libraries(osrm-cli ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM)
|
||||
target_link_libraries(osrm-cli ${TBB_LIBRARIES})
|
||||
add_executable(osrm-io-benchmark tools/io-benchmark.cpp $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:LOGGER>)
|
||||
@ -321,7 +321,8 @@ if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
install(TARGETS osrm-springclean DESTINATION bin)
|
||||
endif()
|
||||
|
||||
file(GLOB InstallGlob Include/osrm/*.h Library/OSRM.h)
|
||||
file(GLOB InstallGlob Include/osrm/*.hpp Library/OSRM.h)
|
||||
file(GLOB VariantGlob Include/variant/*.hpp)
|
||||
|
||||
# Add RPATH info to executables so that when they are run after being installed
|
||||
# (i.e., from /usr/local/bin/) the linker can find library dependencies. For
|
||||
@ -332,6 +333,7 @@ set_property(TARGET osrm-datastore PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
install(FILES ${InstallGlob} DESTINATION include/osrm)
|
||||
install(FILES ${VariantGlob} DESTINATION include/variant)
|
||||
install(TARGETS osrm-extract DESTINATION bin)
|
||||
install(TARGETS osrm-prepare DESTINATION bin)
|
||||
install(TARGETS osrm-datastore DESTINATION bin)
|
||||
|
@ -25,8 +25,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
#ifndef COORDINATE_HPP_
|
||||
#define COORDINATE_HPP_
|
||||
|
||||
#include <iosfwd> //for std::ostream
|
||||
#include <string>
|
||||
@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr float COORDINATE_PRECISION = 1000000.f;
|
||||
constexpr static const float COORDINATE_PRECISION = 1000000.f;
|
||||
}
|
||||
struct FixedPointCoordinate
|
||||
{
|
||||
@ -110,4 +110,4 @@ inline std::ostream &operator<<(std::ostream &out_stream, FixedPointCoordinate c
|
||||
return out_stream;
|
||||
}
|
||||
|
||||
#endif /* FIXED_POINT_COORDINATE_H_ */
|
||||
#endif /* COORDINATE_HPP_ */
|
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ROUTE_PARAMETERS_H
|
||||
#define ROUTE_PARAMETERS_H
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/fusion/container/vector/vector_fwd.hpp>
|
||||
|
||||
@ -40,7 +40,7 @@ struct RouteParameters
|
||||
RouteParameters();
|
||||
|
||||
void setZoomLevel(const short level);
|
||||
|
||||
|
||||
void setNumberOfResults(const short number);
|
||||
|
||||
void setAlternateRouteFlag(const bool flag);
|
@ -28,16 +28,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef OSRM_H
|
||||
#define OSRM_H
|
||||
|
||||
#include <osrm/ServerPaths.h>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class OSRM_impl;
|
||||
struct RouteParameters;
|
||||
|
||||
namespace http
|
||||
namespace JSON
|
||||
{
|
||||
class Reply;
|
||||
struct Object;
|
||||
}
|
||||
|
||||
class OSRM
|
||||
@ -48,7 +48,7 @@ class OSRM
|
||||
public:
|
||||
explicit OSRM(ServerPaths paths, const bool use_shared_memory = false);
|
||||
~OSRM();
|
||||
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
||||
int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result);
|
||||
};
|
||||
|
||||
#endif // OSRM_H
|
||||
|
@ -30,10 +30,6 @@ namespace boost { namespace interprocess { class named_mutex; } }
|
||||
#include "OSRM_impl.h"
|
||||
#include "OSRM.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include "../plugins/distance_table.hpp"
|
||||
#include "../plugins/hello_world.hpp"
|
||||
#include "../plugins/locate.hpp"
|
||||
@ -52,6 +48,9 @@ namespace boost { namespace interprocess { class named_mutex; } }
|
||||
#include <boost/interprocess/sync/named_condition.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
|
||||
#include <osrm/route_parameters.hpp>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
@ -99,13 +98,12 @@ void OSRM_impl::RegisterPlugin(BasePlugin *plugin)
|
||||
plugin_map.emplace(plugin->GetDescriptor(), plugin);
|
||||
}
|
||||
|
||||
void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||
int OSRM_impl::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result)
|
||||
{
|
||||
const PluginMap::const_iterator &iter = plugin_map.find(route_parameters.service);
|
||||
|
||||
if (plugin_map.end() != iter)
|
||||
{
|
||||
reply.status = http::Reply::ok;
|
||||
if (barrier)
|
||||
{
|
||||
// lock update pending
|
||||
@ -126,7 +124,7 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||
->CheckAndReloadFacade();
|
||||
}
|
||||
|
||||
iter->second->HandleRequest(route_parameters, reply);
|
||||
iter->second->HandleRequest(route_parameters, json_result);
|
||||
if (barrier)
|
||||
{
|
||||
// lock query
|
||||
@ -143,10 +141,11 @@ void OSRM_impl::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||
barrier->no_running_queries_condition.notify_all();
|
||||
}
|
||||
}
|
||||
return 200;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return 400;
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +158,7 @@ OSRM::OSRM(ServerPaths paths, const bool use_shared_memory)
|
||||
|
||||
OSRM::~OSRM() { OSRM_pimpl_.reset(); }
|
||||
|
||||
void OSRM::RunQuery(RouteParameters &route_parameters, http::Reply &reply)
|
||||
int OSRM::RunQuery(RouteParameters &route_parameters, JSON::Object &json_result)
|
||||
{
|
||||
OSRM_pimpl_->RunQuery(route_parameters, reply);
|
||||
return OSRM_pimpl_->RunQuery(route_parameters, json_result);
|
||||
}
|
||||
|
@ -32,7 +32,8 @@ class BasePlugin;
|
||||
namespace http { class Reply; }
|
||||
struct RouteParameters;
|
||||
|
||||
#include <osrm/ServerPaths.h>
|
||||
#include <osrm/json_container.hpp>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
#include "../data_structures/query_edge.hpp"
|
||||
|
||||
@ -52,7 +53,7 @@ class OSRM_impl
|
||||
OSRM_impl(ServerPaths paths, const bool use_shared_memory);
|
||||
OSRM_impl(const OSRM_impl &) = delete;
|
||||
virtual ~OSRM_impl();
|
||||
void RunQuery(RouteParameters &route_parameters, http::Reply &reply);
|
||||
int RunQuery(RouteParameters &route_parameters, JSON::Object &json_result);
|
||||
|
||||
private:
|
||||
void RegisterPlugin(BasePlugin *plugin);
|
||||
|
@ -30,10 +30,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// #include "RequestParser.h"
|
||||
#include "Http/CompressionType.h"
|
||||
#include "Http/Reply.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
@ -39,7 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../../Util/string_util.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -43,8 +43,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../../Util/graph_loader.hpp"
|
||||
#include "../../Util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<EdgeDataT>
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include "Reply.h"
|
||||
|
||||
#include "../../Util/cast.hpp"
|
||||
|
||||
|
@ -28,17 +28,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "RequestHandler.h"
|
||||
|
||||
#include "APIGrammar.h"
|
||||
#include "Http/Reply.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/xml_renderer.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/route_parameters.hpp>
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@ -84,13 +85,14 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply
|
||||
auto iter = request.begin();
|
||||
const bool result = boost::spirit::qi::parse(iter, request.end(), api_parser);
|
||||
|
||||
JSON::Object json_result;
|
||||
// check if the was an error with the request
|
||||
if (!result || (iter != request.end()))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
reply.content.clear();
|
||||
const auto position = std::distance(request.begin(), iter);
|
||||
JSON::Object json_result;
|
||||
|
||||
json_result.values["status"] = 400;
|
||||
std::string message = "Query string malformed close to position ";
|
||||
message += cast::integral_to_string(position);
|
||||
@ -107,29 +109,41 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply
|
||||
const std::string json_p = (route_parameters.jsonp_parameter + "(");
|
||||
reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
|
||||
}
|
||||
routing_machine->RunQuery(route_parameters, reply);
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{ // append brace to jsonp response
|
||||
reply.content.push_back(')');
|
||||
const auto return_code = routing_machine->RunQuery(route_parameters, json_result);
|
||||
if (200 != return_code)
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
reply.content.clear();
|
||||
json_result.values["status"] = 400;
|
||||
std::string message = "Bad Request";
|
||||
json_result.values["status_message"] = message;
|
||||
JSON::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// set headers
|
||||
reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size()));
|
||||
if ("gpx" == route_parameters.output_format)
|
||||
{ // gpx file
|
||||
JSON::gpx_render(reply.content, json_result.values["route"]);
|
||||
reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8");
|
||||
reply.headers.emplace_back("Content-Disposition", "attachment; filename=\"route.gpx\"");
|
||||
}
|
||||
else if (route_parameters.jsonp_parameter.empty())
|
||||
{ // json file
|
||||
JSON::render(reply.content, json_result);
|
||||
reply.headers.emplace_back("Content-Type", "application/json; charset=UTF-8");
|
||||
reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.json\"");
|
||||
}
|
||||
else
|
||||
{ // jsonp
|
||||
JSON::render(reply.content, json_result);
|
||||
reply.headers.emplace_back("Content-Type", "text/javascript; charset=UTF-8");
|
||||
reply.headers.emplace_back("Content-Disposition", "inline; filename=\"response.js\"");
|
||||
}
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{ // append brace to jsonp response
|
||||
reply.content.push_back(')');
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define REQUEST_PARSER_H
|
||||
|
||||
#include "Http/CompressionType.h"
|
||||
#include <osrm/Header.h>
|
||||
#include "Http/Header.h"
|
||||
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
@ -27,12 +27,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../../algorithms/douglas_peucker.hpp"
|
||||
#include "../../data_structures/segment_information.hpp"
|
||||
#include "../../Include/osrm/Coordinate.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/mpl/list.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(douglas_peucker)
|
||||
|
@ -31,12 +31,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../../Util/floating_point.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/mpl/list.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <random>
|
||||
#include <unordered_set>
|
||||
|
||||
|
@ -34,7 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "osrm_exception.hpp"
|
||||
#include "simple_logger.hpp"
|
||||
|
||||
#include <osrm/ServerPaths.h>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
@ -33,11 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "osrm_exception.hpp"
|
||||
#include "simple_logger.hpp"
|
||||
|
||||
#include <osrm/ServerPaths.h>
|
||||
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
|
@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "TrigonometryTables.h"
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -31,9 +31,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef JSON_RENDERER_HPP
|
||||
#define JSON_RENDERER_HPP
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "cast.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
namespace JSON {
|
||||
|
||||
struct Renderer : mapbox::util::static_visitor<>
|
||||
|
@ -28,9 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef XML_RENDERER_HPP
|
||||
#define XML_RENDERER_HPP
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "cast.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
namespace JSON {
|
||||
|
||||
struct XMLToArrayRenderer : mapbox::util::static_visitor<>
|
||||
|
@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "polyline_compressor.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
std::string PolylineCompressor::encode_vector(std::vector<int> &numbers) const
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "polyline_compressor.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
JSON::String
|
||||
PolylineFormatter::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
|
@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
struct SegmentInformation;
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -42,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/std_hash.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
@ -29,10 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/shared_memory_vector_wrapper.hpp"
|
||||
#include "../data_structures/static_rtree.hpp"
|
||||
#include "../data_structures/edge_based_node.hpp"
|
||||
#include "../Util/BoostFileSystemFix.h"
|
||||
#include "../data_structures/edge_based_node.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <random>
|
||||
|
||||
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
|
||||
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 INPUT_READER_FACTORY_H
|
||||
#define INPUT_READER_FACTORY_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <bzlib.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
struct BZ2Context
|
||||
{
|
||||
FILE *file;
|
||||
BZFILE *bz2;
|
||||
int error;
|
||||
int nUnused;
|
||||
char unused[BZ_MAX_UNUSED];
|
||||
};
|
||||
|
||||
int readFromBz2Stream(void *pointer, char *buffer, int len)
|
||||
{
|
||||
void *unusedTmpVoid = nullptr;
|
||||
char *unusedTmp = nullptr;
|
||||
BZ2Context *context = (BZ2Context *)pointer;
|
||||
int read = 0;
|
||||
while (0 == read &&
|
||||
!(BZ_STREAM_END == context->error && 0 == context->nUnused && feof(context->file)))
|
||||
{
|
||||
read = BZ2_bzRead(&context->error, context->bz2, buffer, len);
|
||||
if (BZ_OK == context->error)
|
||||
{
|
||||
return read;
|
||||
}
|
||||
else if (BZ_STREAM_END == context->error)
|
||||
{
|
||||
BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused);
|
||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadGetUnused");
|
||||
unusedTmp = (char *)unusedTmpVoid;
|
||||
for (int i = 0; i < context->nUnused; i++)
|
||||
{
|
||||
context->unused[i] = unusedTmp[i];
|
||||
}
|
||||
BZ2_bzReadClose(&context->error, context->bz2);
|
||||
BOOST_ASSERT_MSG(BZ_OK == context->error, "Could not BZ2_bzReadClose");
|
||||
context->error = BZ_STREAM_END; // set to the stream end for next call to this function
|
||||
if (0 == context->nUnused && feof(context->file))
|
||||
{
|
||||
return read;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->bz2 = BZ2_bzReadOpen(
|
||||
&context->error, context->file, 0, 0, context->unused, context->nUnused);
|
||||
BOOST_ASSERT_MSG(nullptr != context->bz2, "Could not open file");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT_MSG(false, "Could not read bz2 file");
|
||||
}
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
int closeBz2Stream(void *pointer)
|
||||
{
|
||||
BZ2Context *context = (BZ2Context *)pointer;
|
||||
fclose(context->file);
|
||||
delete context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
xmlTextReaderPtr inputReaderFactory(const char *name)
|
||||
{
|
||||
std::string inputName(name);
|
||||
|
||||
if (inputName.find(".osm.bz2") != std::string::npos)
|
||||
{
|
||||
BZ2Context *context = new BZ2Context();
|
||||
context->error = false;
|
||||
context->file = fopen(name, "r");
|
||||
int error;
|
||||
context->bz2 =
|
||||
BZ2_bzReadOpen(&error, context->file, 0, 0, context->unused, context->nUnused);
|
||||
if (context->bz2 == nullptr || context->file == nullptr)
|
||||
{
|
||||
delete context;
|
||||
return nullptr;
|
||||
}
|
||||
return xmlReaderForIO(readFromBz2Stream, closeBz2Stream, (void *)context, nullptr, nullptr, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return xmlNewTextReaderFilename(name);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INPUT_READER_FACTORY_H
|
@ -1,483 +1,484 @@
|
||||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#ifndef NDEBUG
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#endif
|
||||
#include "../Util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y_coordinate_vector(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||
<< ", bits: " << y_coordinate_vector;
|
||||
}
|
||||
if (0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x_coordinate_vector(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||
<< ", bits: " << x_coordinate_vector;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset()
|
||||
{
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const
|
||||
{
|
||||
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
bool FixedPointCoordinate::is_valid() const
|
||||
{
|
||||
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
const double earth = 6372797.560856;
|
||||
return earth * cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateEuclideanDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float RAD = 0.017453292519943295769236907684886f;
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
const float earth_radius = 6372797.560856f;
|
||||
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &point)
|
||||
{
|
||||
// initialize values
|
||||
const float x_value = static_cast<float>(lat2y(point.lat / COORDINATE_PRECISION));
|
||||
const float y_value = point.lon / COORDINATE_PRECISION;
|
||||
float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
|
||||
float b = source_coordinate.lon / COORDINATE_PRECISION;
|
||||
float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
|
||||
float d = target_coordinate.lon / COORDINATE_PRECISION;
|
||||
float p, q;
|
||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
const float slope = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
|
||||
(1.f + slope * slope);
|
||||
q = b + slope * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y_value;
|
||||
}
|
||||
|
||||
float ratio;
|
||||
bool inverse_ratio = false;
|
||||
|
||||
// straight line segment on equator
|
||||
if (std::abs(c) < std::numeric_limits<float>::epsilon() &&
|
||||
std::abs(a) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = (q - b) / (d - b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::abs(c) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
// swap start/end
|
||||
std::swap(a, c);
|
||||
std::swap(b, d);
|
||||
inverse_ratio = true;
|
||||
}
|
||||
|
||||
float nY = (d * p - c * q) / (a * d - b * c);
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c;
|
||||
}
|
||||
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (target_coordinate == point ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// we need to do this, if we switched start/end coordinates
|
||||
if (inverse_ratio)
|
||||
{
|
||||
ratio = 1.0f - ratio;
|
||||
}
|
||||
|
||||
// compute the nearest location
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{ // point is "left" of edge
|
||||
nearest_location = source_coordinate;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{ // point is "right" of edge
|
||||
nearest_location = target_coordinate;
|
||||
}
|
||||
else
|
||||
{ // point lies in between
|
||||
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||
const double a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate)
|
||||
{
|
||||
const float lon_diff =
|
||||
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||
const float lon_delta = DegreeToRadian(lon_diff);
|
||||
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = sin(lon_delta) * cos(lat2);
|
||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
const float lon_delta =
|
||||
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||
const float x_value =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y_value, x_value));
|
||||
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::RadianToDegree(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
// This distance computation does integer arithmetic only and is a lot faster than
|
||||
// the other distance function which are numerically correct('ish).
|
||||
// It preserves some order among the elements that make it useful for certain purposes
|
||||
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
|
||||
const FixedPointCoordinate &input_point,
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target)
|
||||
{
|
||||
// initialize values
|
||||
const float x = static_cast<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
|
||||
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||
const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
|
||||
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const float c = static_cast<float>(lat2y(segment_target.lat / COORDINATE_PRECISION));
|
||||
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||
|
||||
float p, q;
|
||||
if (a == c)
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
|
||||
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == input_point) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
// compute target quasi-location
|
||||
int dx, dy;
|
||||
if (ratio < 0.f)
|
||||
{
|
||||
dx = input_point.lon - segment_source.lon;
|
||||
dy = input_point.lat - segment_source.lat;
|
||||
}
|
||||
else if (ratio > 1.f)
|
||||
{
|
||||
dx = input_point.lon - segment_target.lon;
|
||||
dy = input_point.lat - segment_target.lat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
// return an approximation in the plane
|
||||
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||
}
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, 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.
|
||||
|
||||
*/
|
||||
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#ifndef NDEBUG
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#endif
|
||||
#include "../Util/string_util.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y_coordinate_vector(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat
|
||||
<< ", bits: " << y_coordinate_vector;
|
||||
}
|
||||
if (0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x_coordinate_vector(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon
|
||||
<< ", bits: " << x_coordinate_vector;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset()
|
||||
{
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const
|
||||
{
|
||||
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
bool FixedPointCoordinate::is_valid() const
|
||||
{
|
||||
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||
const double earth = 6372797.560856;
|
||||
return earth * cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &coordinate_1,
|
||||
const FixedPointCoordinate &coordinate_2)
|
||||
{
|
||||
return ApproximateEuclideanDistance(
|
||||
coordinate_1.lat, coordinate_1.lon, coordinate_2.lat, coordinate_2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float RAD = 0.017453292519943295769236907684886f;
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x_value = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.f);
|
||||
const float y_value = float_lat2 - float_lat1;
|
||||
const float earth_radius = 6372797.560856f;
|
||||
return sqrt(x_value * x_value + y_value * y_value) * earth_radius;
|
||||
}
|
||||
|
||||
float
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &source_coordinate,
|
||||
const FixedPointCoordinate &target_coordinate,
|
||||
const FixedPointCoordinate &point)
|
||||
{
|
||||
// initialize values
|
||||
const float x_value = static_cast<float>(lat2y(point.lat / COORDINATE_PRECISION));
|
||||
const float y_value = point.lon / COORDINATE_PRECISION;
|
||||
float a = static_cast<float>(lat2y(source_coordinate.lat / COORDINATE_PRECISION));
|
||||
float b = source_coordinate.lon / COORDINATE_PRECISION;
|
||||
float c = static_cast<float>(lat2y(target_coordinate.lat / COORDINATE_PRECISION));
|
||||
float d = target_coordinate.lon / COORDINATE_PRECISION;
|
||||
float p, q;
|
||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
const float slope = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x_value + (slope * y_value)) + (slope * slope * a - slope * b)) /
|
||||
(1.f + slope * slope);
|
||||
q = b + slope * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y_value;
|
||||
}
|
||||
|
||||
float ratio;
|
||||
bool inverse_ratio = false;
|
||||
|
||||
// straight line segment on equator
|
||||
if (std::abs(c) < std::numeric_limits<float>::epsilon() &&
|
||||
std::abs(a) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = (q - b) / (d - b);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (std::abs(c) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
// swap start/end
|
||||
std::swap(a, c);
|
||||
std::swap(b, d);
|
||||
inverse_ratio = true;
|
||||
}
|
||||
|
||||
float nY = (d * p - c * q) / (a * d - b * c);
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c;
|
||||
}
|
||||
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (target_coordinate == point ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// we need to do this, if we switched start/end coordinates
|
||||
if (inverse_ratio)
|
||||
{
|
||||
ratio = 1.0f - ratio;
|
||||
}
|
||||
|
||||
// compute the nearest location
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{ // point is "left" of edge
|
||||
nearest_location = source_coordinate;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{ // point is "right" of edge
|
||||
nearest_location = target_coordinate;
|
||||
}
|
||||
else
|
||||
{ // point lies in between
|
||||
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
return FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &ratio)
|
||||
{
|
||||
BOOST_ASSERT(query_location.is_valid());
|
||||
|
||||
// initialize values
|
||||
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||
const double a = lat2y(segment_source.lat / COORDINATE_PRECISION);
|
||||
const double b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const double c = lat2y(segment_target.lat / COORDINATE_PRECISION);
|
||||
const double d = segment_target.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1.f / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.f;
|
||||
}
|
||||
|
||||
// compute ratio
|
||||
ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == query_location ? 1.f : 0.f);
|
||||
}
|
||||
else if (std::abs(ratio) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 0.f;
|
||||
}
|
||||
else if (std::abs(ratio - 1.f) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
ratio = 1.f;
|
||||
}
|
||||
|
||||
// compute nearest location
|
||||
BOOST_ASSERT(!std::isnan(ratio));
|
||||
if (ratio <= 0.f)
|
||||
{
|
||||
nearest_location = segment_source;
|
||||
}
|
||||
else if (ratio >= 1.f)
|
||||
{
|
||||
nearest_location = segment_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
nearest_location.lon = static_cast<int>(q * COORDINATE_PRECISION);
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.is_valid());
|
||||
|
||||
const float approximate_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximate_distance);
|
||||
return approximate_distance;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &first_coordinate,
|
||||
const FixedPointCoordinate &second_coordinate)
|
||||
{
|
||||
const float lon_diff =
|
||||
second_coordinate.lon / COORDINATE_PRECISION - first_coordinate.lon / COORDINATE_PRECISION;
|
||||
const float lon_delta = DegreeToRadian(lon_diff);
|
||||
const float lat1 = DegreeToRadian(first_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(second_coordinate.lat / COORDINATE_PRECISION);
|
||||
const float y = sin(lon_delta) * cos(lat2);
|
||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
const float lon_delta =
|
||||
DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||
const float y_value = std::sin(lon_delta) * std::cos(lat2);
|
||||
const float x_value =
|
||||
std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(lon_delta);
|
||||
float result = RadianToDegree(std::atan2(y_value, x_value));
|
||||
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
||||
{
|
||||
return degree * (static_cast<float>(M_PI) / 180.f);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::RadianToDegree(const float radian)
|
||||
{
|
||||
return radian * (180.f * static_cast<float>(M_1_PI));
|
||||
}
|
||||
|
||||
// This distance computation does integer arithmetic only and is a lot faster than
|
||||
// the other distance function which are numerically correct('ish).
|
||||
// It preserves some order among the elements that make it useful for certain purposes
|
||||
int FixedPointCoordinate::OrderedPerpendicularDistanceApproximation(
|
||||
const FixedPointCoordinate &input_point,
|
||||
const FixedPointCoordinate &segment_source,
|
||||
const FixedPointCoordinate &segment_target)
|
||||
{
|
||||
// initialize values
|
||||
const float x = static_cast<float>(lat2y(input_point.lat / COORDINATE_PRECISION));
|
||||
const float y = input_point.lon / COORDINATE_PRECISION;
|
||||
const float a = static_cast<float>(lat2y(segment_source.lat / COORDINATE_PRECISION));
|
||||
const float b = segment_source.lon / COORDINATE_PRECISION;
|
||||
const float c = static_cast<float>(lat2y(segment_target.lat / COORDINATE_PRECISION));
|
||||
const float d = segment_target.lon / COORDINATE_PRECISION;
|
||||
|
||||
float p, q;
|
||||
if (a == c)
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1.f + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
|
||||
const float nY = (d * p - c * q) / (a * d - b * c);
|
||||
float ratio = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(ratio))
|
||||
{
|
||||
ratio = (segment_target == input_point) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
// compute target quasi-location
|
||||
int dx, dy;
|
||||
if (ratio < 0.f)
|
||||
{
|
||||
dx = input_point.lon - segment_source.lon;
|
||||
dy = input_point.lat - segment_source.lat;
|
||||
}
|
||||
else if (ratio > 1.f)
|
||||
{
|
||||
dx = input_point.lon - segment_target.lon;
|
||||
dy = input_point.lat - segment_target.lat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
dx = input_point.lon - static_cast<int>(q * COORDINATE_PRECISION);
|
||||
dy = input_point.lat - static_cast<int>(y2lat(p) * COORDINATE_PRECISION);
|
||||
}
|
||||
|
||||
// return an approximation in the plane
|
||||
return static_cast<int>(sqrt(dx * dx + dy * dy));
|
||||
}
|
@ -31,10 +31,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct EdgeBasedNode
|
||||
|
@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "hilbert_value.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
uint64_t HilbertCode::operator()(const FixedPointCoordinate ¤t_coordinate) const
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -25,15 +25,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RAW_ROUTE_DATA_HPP
|
||||
#define RAW_ROUTE_DATA_HPP
|
||||
#ifndef RAW_ROUTE_DATA_H
|
||||
#define RAW_ROUTE_DATA_H
|
||||
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -63,7 +63,7 @@ struct PathData
|
||||
TravelMode travel_mode : 4;
|
||||
};
|
||||
|
||||
struct RawRouteData
|
||||
struct InternalRouteResult
|
||||
{
|
||||
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||
std::vector<PathData> unpacked_alternative;
|
||||
@ -80,11 +80,11 @@ struct RawRouteData
|
||||
return (leg != unpacked_path_segments.size() - 1);
|
||||
}
|
||||
|
||||
RawRouteData() :
|
||||
InternalRouteResult() :
|
||||
shortest_path_length(INVALID_EDGE_WEIGHT),
|
||||
alternative_path_length(INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RAW_ROUTE_DATA_HPP
|
||||
#endif // RAW_ROUTE_DATA_H
|
@ -28,10 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef PHANTOM_NODES_H
|
||||
#define PHANTOM_NODES_H
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
@ -30,10 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
|
||||
struct QueryNode
|
||||
|
@ -25,12 +25,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/RouteParameters.h>
|
||||
|
||||
#include <boost/fusion/container/vector.hpp>
|
||||
#include <boost/fusion/sequence/intrinsic.hpp>
|
||||
#include <boost/fusion/include/at_c.hpp>
|
||||
|
||||
#include <osrm/route_parameters.hpp>
|
||||
|
||||
RouteParameters::RouteParameters()
|
||||
: zoom_level(18), print_instructions(false), alternate_route(true), geometry(true),
|
||||
compression(true), deprecatedAPI(false), uturn_default(false), check_sum(-1), num_results(1)
|
||||
|
@ -33,7 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
// Struct fits everything in one cache line
|
||||
struct SegmentInformation
|
||||
|
@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/timing_util.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "Util/FingerPrint.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
using RTreeLeaf = BaseDataFacade<QueryEdge::EdgeData>::RTreeLeaf;
|
||||
using RTreeNode = StaticRTree<RTreeLeaf, ShM<FixedPointCoordinate, true>::vector, true>::TreeNode;
|
||||
|
@ -27,11 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "description_factory.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../algorithms/polyline_formatter.hpp"
|
||||
#include "../data_structures/raw_route_data.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
|
||||
DescriptionFactory::DescriptionFactory() : entire_length(0) { via_indices.push_back(0); }
|
||||
|
@ -30,14 +30,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../algorithms/douglas_peucker.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -28,17 +28,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef DESCRIPTOR_BASE_HPP
|
||||
#define DESCRIPTOR_BASE_HPP
|
||||
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../data_structures/raw_route_data.hpp"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
||||
struct DescriptorTable : public std::unordered_map<std::string, unsigned>
|
||||
{
|
||||
unsigned get_id(const std::string &key)
|
||||
@ -80,8 +79,8 @@ template <class DataFacadeT> class BaseDescriptor
|
||||
BaseDescriptor() {}
|
||||
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BaseDescriptor() {}
|
||||
virtual void Run(const RawRouteData &raw_route, http::Reply &reply) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
||||
virtual void Run(const InternalRouteResult &, JSON::Object &) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig &) = 0;
|
||||
};
|
||||
|
||||
#endif // DESCRIPTOR_BASE_HPP
|
||||
|
@ -29,9 +29,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define GPX_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Util/xml_renderer.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
@ -40,7 +41,7 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
DescriptorConfig config;
|
||||
DataFacadeT *facade;
|
||||
|
||||
void AddRoutePoint(const FixedPointCoordinate &coordinate, JSON::Array &json_result)
|
||||
void AddRoutePoint(const FixedPointCoordinate &coordinate, JSON::Array &json_route)
|
||||
{
|
||||
JSON::Object json_lat;
|
||||
JSON::Object json_lon;
|
||||
@ -58,7 +59,7 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
json_row.values.push_back(json_lon);
|
||||
JSON::Object entry;
|
||||
entry.values["rtept"] = json_row;
|
||||
json_result.values.push_back(entry);
|
||||
json_route.values.push_back(entry);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -66,13 +67,13 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
|
||||
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||
void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) final
|
||||
{
|
||||
JSON::Array json_result;
|
||||
JSON::Array json_route;
|
||||
if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location,
|
||||
json_result);
|
||||
json_route);
|
||||
|
||||
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||
{
|
||||
@ -80,13 +81,14 @@ template <class DataFacadeT> class GPXDescriptor final : public BaseDescriptor<D
|
||||
{
|
||||
const FixedPointCoordinate current_coordinate =
|
||||
facade->GetCoordinateOfNode(path_data.node);
|
||||
AddRoutePoint(current_coordinate, json_result);
|
||||
AddRoutePoint(current_coordinate, json_route);
|
||||
}
|
||||
}
|
||||
AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location,
|
||||
json_result);
|
||||
json_route);
|
||||
}
|
||||
JSON::gpx_render(reply.content, json_result);
|
||||
// JSON::gpx_render(reply.content, json_route);
|
||||
json_result.values["route"] = json_route;
|
||||
}
|
||||
};
|
||||
#endif // GPX_DESCRIPTOR_HPP
|
||||
|
@ -1,393 +1,393 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, 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 JSON_DESCRIPTOR_HPP
|
||||
#define JSON_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "description_factory.hpp"
|
||||
#include "../algorithms/object_encoder.hpp"
|
||||
#include "../algorithms/route_name_extraction.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../Util/bearing.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory, alternate_description_factory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
unsigned name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||
unsigned name_id;
|
||||
int length;
|
||||
unsigned position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||
|
||||
public:
|
||||
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
|
||||
unsigned DescribeLeg(const std::vector<PathData> route_leg,
|
||||
const PhantomNodes &leg_phantoms,
|
||||
const bool target_traversed_in_reverse,
|
||||
const bool is_via_leg)
|
||||
{
|
||||
unsigned added_element_count = 0;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
description_factory.SetEndSegment(
|
||||
leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg);
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
void Run(const RawRouteData &raw_route, http::Reply &reply) final
|
||||
{
|
||||
JSON::Object json_result;
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
json_result.values["status"] = 207;
|
||||
json_result.values["status_message"] = "Cannot find route between points";
|
||||
JSON::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if first segment is non-zero
|
||||
std::string road_name = facade->GetEscapedNameForNameID(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.name_id);
|
||||
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.source_traversed_in_reverse.front());
|
||||
json_result.values["status"] = 0;
|
||||
json_result.values["status_message"] = "Found route between points";
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
const int added_segments =
|
||||
#endif
|
||||
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||
raw_route.segment_end_coordinates[i],
|
||||
raw_route.target_traversed_in_reverse[i],
|
||||
raw_route.is_via_leg(i));
|
||||
BOOST_ASSERT(0 < added_segments);
|
||||
}
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value route_geometry =
|
||||
description_factory.AppendGeometryString(config.encode_geometry);
|
||||
json_result.values["route_geometry"] = route_geometry;
|
||||
}
|
||||
if (config.instructions)
|
||||
{
|
||||
JSON::Array json_route_instructions;
|
||||
BuildTextualDescription(description_factory,
|
||||
json_route_instructions,
|
||||
raw_route.shortest_path_length,
|
||||
shortest_path_segments);
|
||||
json_result.values["route_instructions"] = json_route_instructions;
|
||||
}
|
||||
description_factory.BuildRouteSummary(description_factory.get_entire_length(),
|
||||
raw_route.shortest_path_length);
|
||||
JSON::Object json_route_summary;
|
||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||
json_route_summary.values["start_point"] =
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||
json_route_summary.values["end_point"] =
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||
json_result.values["route_summary"] = json_route_summary;
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
JSON::Array json_via_points_array;
|
||||
JSON::Array json_first_coordinate;
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_first_coordinate);
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
std::string tmp;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_coordinate);
|
||||
}
|
||||
json_result.values["via_points"] = json_via_points_array;
|
||||
|
||||
JSON::Array json_via_indices_array;
|
||||
|
||||
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||
shortest_leg_end_indices.begin(),
|
||||
shortest_leg_end_indices.end());
|
||||
json_result.values["via_indices"] = json_via_indices_array;
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::True();
|
||||
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||
alternate_description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.front());
|
||||
// Get all the coordinates for the computed route
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_description_factory.AppendSegment(current, path_data);
|
||||
}
|
||||
alternate_description_factory.SetEndSegment(
|
||||
raw_route.segment_end_coordinates.back().target_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.back());
|
||||
alternate_description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value alternate_geometry_string =
|
||||
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||
JSON::Array json_alternate_geometries_array;
|
||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||
}
|
||||
// Generate instructions for each alternative (simulated here)
|
||||
JSON::Array json_alt_instructions;
|
||||
JSON::Array json_current_alt_instructions;
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(alternate_description_factory,
|
||||
json_current_alt_instructions,
|
||||
raw_route.alternative_path_length,
|
||||
alternative_path_segments);
|
||||
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||
}
|
||||
alternate_description_factory.BuildRouteSummary(
|
||||
alternate_description_factory.get_entire_length(), raw_route.alternative_path_length);
|
||||
|
||||
JSON::Object json_alternate_route_summary;
|
||||
JSON::Array json_alternate_route_summary_array;
|
||||
json_alternate_route_summary.values["total_distance"] =
|
||||
alternate_description_factory.summary.distance;
|
||||
json_alternate_route_summary.values["total_time"] =
|
||||
alternate_description_factory.summary.duration;
|
||||
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
|
||||
alternate_description_factory.summary.source_name_id);
|
||||
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
|
||||
alternate_description_factory.summary.target_name_id);
|
||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||
|
||||
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||
alternate_description_factory.GetViaIndices();
|
||||
JSON::Array json_altenative_indices_array;
|
||||
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||
alternate_leg_end_indices.begin(),
|
||||
alternate_leg_end_indices.end());
|
||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||
}
|
||||
else
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::False();
|
||||
}
|
||||
|
||||
// Get Names for both routes
|
||||
RouteNames route_names =
|
||||
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||
JSON::Array json_route_names;
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||
json_result.values["route_name"] = json_route_names;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
JSON::Array json_alternate_names_array;
|
||||
JSON::Array json_alternate_names;
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||
}
|
||||
|
||||
JSON::Object json_hint_object;
|
||||
json_hint_object.values["checksum"] = facade->GetCheckSum();
|
||||
JSON::Array json_location_hint_array;
|
||||
std::string hint;
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||
{
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
}
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
json_hint_object.values["locations"] = json_location_hint_array;
|
||||
json_result.values["hint_data"] = json_hint_object;
|
||||
|
||||
// render the content to the output array
|
||||
TIMER_START(route_render);
|
||||
JSON::render(reply.content, json_result);
|
||||
TIMER_STOP(route_render);
|
||||
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
JSON::Array &json_instruction_array,
|
||||
const int route_length,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
JSON::Array json_instruction_row;
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string current_turn_instruction;
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
temp_instruction =
|
||||
cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||
current_turn_instruction += temp_instruction;
|
||||
current_turn_instruction += "-";
|
||||
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||
current_turn_instruction += temp_instruction;
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||
current_turn_instruction += temp_instruction;
|
||||
}
|
||||
json_instruction_row.values.push_back(current_turn_instruction);
|
||||
|
||||
json_instruction_row.values.push_back(
|
||||
facade->GetEscapedNameForNameID(segment.name_id));
|
||||
json_instruction_row.values.push_back(std::round(segment.length));
|
||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||
json_instruction_row.values.push_back(
|
||||
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||
const double bearing_value = (segment.bearing / 10.);
|
||||
json_instruction_row.values.push_back(Bearing::Get(bearing_value));
|
||||
json_instruction_row.values.push_back(
|
||||
static_cast<unsigned>(round(bearing_value)));
|
||||
json_instruction_row.values.push_back(segment.travel_mode);
|
||||
|
||||
route_segments_list.emplace_back(
|
||||
segment.name_id,
|
||||
static_cast<int>(segment.length),
|
||||
static_cast<unsigned>(route_segments_list.size()));
|
||||
json_instruction_array.values.push_back(json_instruction_row);
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
|
||||
JSON::Array json_last_instruction_row;
|
||||
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||
json_last_instruction_row.values.push_back(temp_instruction);
|
||||
json_last_instruction_row.values.push_back("");
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back("0m");
|
||||
json_last_instruction_row.values.push_back(Bearing::Get(0.0));
|
||||
json_last_instruction_row.values.push_back(0.);
|
||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_HPP */
|
||||
/*
|
||||
|
||||
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 JSON_DESCRIPTOR_HPP
|
||||
#define JSON_DESCRIPTOR_HPP
|
||||
|
||||
#include "descriptor_base.hpp"
|
||||
#include "description_factory.hpp"
|
||||
#include "../algorithms/object_encoder.hpp"
|
||||
#include "../algorithms/route_name_extraction.hpp"
|
||||
#include "../data_structures/segment_information.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
#include "../Util/bearing.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory, alternate_description_factory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INVALID_NAMEID), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
unsigned name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(INVALID_NAMEID), length(-1), position(0) {}
|
||||
Segment(unsigned n, int l, unsigned p) : name_id(n), length(l), position(p) {}
|
||||
unsigned name_id;
|
||||
int length;
|
||||
unsigned position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||
|
||||
public:
|
||||
explicit JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0) {}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) final { config = c; }
|
||||
|
||||
unsigned DescribeLeg(const std::vector<PathData> route_leg,
|
||||
const PhantomNodes &leg_phantoms,
|
||||
const bool target_traversed_in_reverse,
|
||||
const bool is_via_leg)
|
||||
{
|
||||
unsigned added_element_count = 0;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
description_factory.SetEndSegment(
|
||||
leg_phantoms.target_phantom, target_traversed_in_reverse, is_via_leg);
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
void Run(const InternalRouteResult &raw_route, JSON::Object &json_result) final
|
||||
{
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
json_result.values["status"] = 207;
|
||||
json_result.values["status_message"] = "Cannot find route between points";
|
||||
// JSON::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if first segment is non-zero
|
||||
std::string road_name = facade->GetEscapedNameForNameID(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.name_id);
|
||||
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.source_traversed_in_reverse.front());
|
||||
json_result.values["status"] = 0;
|
||||
json_result.values["status_message"] = "Found route between points";
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.unpacked_path_segments.size()))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
const int added_segments =
|
||||
#endif
|
||||
DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||
raw_route.segment_end_coordinates[i],
|
||||
raw_route.target_traversed_in_reverse[i],
|
||||
raw_route.is_via_leg(i));
|
||||
BOOST_ASSERT(0 < added_segments);
|
||||
}
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value route_geometry =
|
||||
description_factory.AppendGeometryString(config.encode_geometry);
|
||||
json_result.values["route_geometry"] = route_geometry;
|
||||
}
|
||||
if (config.instructions)
|
||||
{
|
||||
JSON::Array json_route_instructions;
|
||||
BuildTextualDescription(description_factory,
|
||||
json_route_instructions,
|
||||
raw_route.shortest_path_length,
|
||||
shortest_path_segments);
|
||||
json_result.values["route_instructions"] = json_route_instructions;
|
||||
}
|
||||
description_factory.BuildRouteSummary(description_factory.get_entire_length(),
|
||||
raw_route.shortest_path_length);
|
||||
JSON::Object json_route_summary;
|
||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||
json_route_summary.values["start_point"] =
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||
json_route_summary.values["end_point"] =
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||
json_result.values["route_summary"] = json_route_summary;
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
JSON::Array json_via_points_array;
|
||||
JSON::Array json_first_coordinate;
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_first_coordinate.values.push_back(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_first_coordinate);
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
std::string tmp;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lat /
|
||||
COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lon /
|
||||
COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_coordinate);
|
||||
}
|
||||
json_result.values["via_points"] = json_via_points_array;
|
||||
|
||||
JSON::Array json_via_indices_array;
|
||||
|
||||
std::vector<unsigned> const &shortest_leg_end_indices = description_factory.GetViaIndices();
|
||||
json_via_indices_array.values.insert(json_via_indices_array.values.end(),
|
||||
shortest_leg_end_indices.begin(),
|
||||
shortest_leg_end_indices.end());
|
||||
json_result.values["via_indices"] = json_via_indices_array;
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::True();
|
||||
BOOST_ASSERT(!raw_route.alt_source_traversed_in_reverse.empty());
|
||||
alternate_description_factory.SetStartSegment(
|
||||
raw_route.segment_end_coordinates.front().source_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.front());
|
||||
// Get all the coordinates for the computed route
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_description_factory.AppendSegment(current, path_data);
|
||||
}
|
||||
alternate_description_factory.SetEndSegment(
|
||||
raw_route.segment_end_coordinates.back().target_phantom,
|
||||
raw_route.alt_source_traversed_in_reverse.back());
|
||||
alternate_description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value alternate_geometry_string =
|
||||
alternate_description_factory.AppendGeometryString(config.encode_geometry);
|
||||
JSON::Array json_alternate_geometries_array;
|
||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||
}
|
||||
// Generate instructions for each alternative (simulated here)
|
||||
JSON::Array json_alt_instructions;
|
||||
JSON::Array json_current_alt_instructions;
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(alternate_description_factory,
|
||||
json_current_alt_instructions,
|
||||
raw_route.alternative_path_length,
|
||||
alternative_path_segments);
|
||||
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||
}
|
||||
alternate_description_factory.BuildRouteSummary(
|
||||
alternate_description_factory.get_entire_length(), raw_route.alternative_path_length);
|
||||
|
||||
JSON::Object json_alternate_route_summary;
|
||||
JSON::Array json_alternate_route_summary_array;
|
||||
json_alternate_route_summary.values["total_distance"] =
|
||||
alternate_description_factory.summary.distance;
|
||||
json_alternate_route_summary.values["total_time"] =
|
||||
alternate_description_factory.summary.duration;
|
||||
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(
|
||||
alternate_description_factory.summary.source_name_id);
|
||||
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(
|
||||
alternate_description_factory.summary.target_name_id);
|
||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||
|
||||
std::vector<unsigned> const &alternate_leg_end_indices =
|
||||
alternate_description_factory.GetViaIndices();
|
||||
JSON::Array json_altenative_indices_array;
|
||||
json_altenative_indices_array.values.insert(json_altenative_indices_array.values.end(),
|
||||
alternate_leg_end_indices.begin(),
|
||||
alternate_leg_end_indices.end());
|
||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||
}
|
||||
else
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::False();
|
||||
}
|
||||
|
||||
// Get Names for both routes
|
||||
RouteNames route_names =
|
||||
GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||
JSON::Array json_route_names;
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||
json_result.values["route_name"] = json_route_names;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
JSON::Array json_alternate_names_array;
|
||||
JSON::Array json_alternate_names;
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||
}
|
||||
|
||||
JSON::Object json_hint_object;
|
||||
json_hint_object.values["checksum"] = facade->GetCheckSum();
|
||||
JSON::Array json_location_hint_array;
|
||||
std::string hint;
|
||||
for (const auto i : osrm::irange<std::size_t>(0, raw_route.segment_end_coordinates.size()))
|
||||
{
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
}
|
||||
ObjectEncoder::EncodeToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
json_hint_object.values["locations"] = json_location_hint_array;
|
||||
json_result.values["hint_data"] = json_hint_object;
|
||||
|
||||
// render the content to the output array
|
||||
// TIMER_START(route_render);
|
||||
// JSON::render(reply.content, json_result);
|
||||
// TIMER_STOP(route_render);
|
||||
// SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
JSON::Array &json_instruction_array,
|
||||
const int route_length,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
JSON::Array json_instruction_row;
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string current_turn_instruction;
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
temp_instruction =
|
||||
cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||
current_turn_instruction += temp_instruction;
|
||||
current_turn_instruction += "-";
|
||||
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
||||
current_turn_instruction += temp_instruction;
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
||||
current_turn_instruction += temp_instruction;
|
||||
}
|
||||
json_instruction_row.values.push_back(current_turn_instruction);
|
||||
|
||||
json_instruction_row.values.push_back(
|
||||
facade->GetEscapedNameForNameID(segment.name_id));
|
||||
json_instruction_row.values.push_back(std::round(segment.length));
|
||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||
json_instruction_row.values.push_back(
|
||||
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||
const double bearing_value = (segment.bearing / 10.);
|
||||
json_instruction_row.values.push_back(Bearing::Get(bearing_value));
|
||||
json_instruction_row.values.push_back(
|
||||
static_cast<unsigned>(round(bearing_value)));
|
||||
json_instruction_row.values.push_back(segment.travel_mode);
|
||||
|
||||
route_segments_list.emplace_back(
|
||||
segment.name_id,
|
||||
static_cast<int>(segment.length),
|
||||
static_cast<unsigned>(route_segments_list.size()));
|
||||
json_instruction_array.values.push_back(json_instruction_row);
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
|
||||
JSON::Array json_last_instruction_row;
|
||||
temp_instruction = cast::integral_to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||
json_last_instruction_row.values.push_back(temp_instruction);
|
||||
json_last_instruction_row.values.push_back("");
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back("0m");
|
||||
json_last_instruction_row.values.push_back(Bearing::Get(0.0));
|
||||
json_last_instruction_row.values.push_back(0.);
|
||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
|
@ -35,7 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/container.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "../data_structures/travel_mode.hpp"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
struct InternalExtractorEdge
|
||||
{
|
||||
InternalExtractorEdge()
|
||||
|
@ -31,7 +31,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "plugin_base.hpp"
|
||||
|
||||
#include "../algorithms/object_encoder.hpp"
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../data_structures/query_edge.hpp"
|
||||
#include "../data_structures/search_engine.hpp"
|
||||
#include "../descriptors/descriptor_base.hpp"
|
||||
@ -40,6 +39,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/string_util.hpp"
|
||||
#include "../Util/timing_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
@ -63,12 +64,11 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
|
||||
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||
int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final
|
||||
{
|
||||
if (!check_all_coordinates(route_parameters.coordinates))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
return 400;
|
||||
}
|
||||
|
||||
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
||||
@ -102,11 +102,9 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
|
||||
|
||||
if (!result_table)
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
return 400;
|
||||
}
|
||||
|
||||
JSON::Object json_object;
|
||||
JSON::Array json_array;
|
||||
const auto number_of_locations = phantom_node_vector.size();
|
||||
for (const auto row : osrm::irange<std::size_t>(0, number_of_locations))
|
||||
@ -117,8 +115,9 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
|
||||
json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
|
||||
json_array.values.push_back(json_row);
|
||||
}
|
||||
json_object.values["distance_table"] = json_array;
|
||||
JSON::render(reply.content, json_object);
|
||||
json_result.values["distance_table"] = json_array;
|
||||
// JSON::render(reply.content, json_object);
|
||||
return 200;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "plugin_base.hpp"
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Util/cast.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
class HelloWorldPlugin final : public BasePlugin
|
||||
@ -46,11 +47,8 @@ class HelloWorldPlugin final : public BasePlugin
|
||||
virtual ~HelloWorldPlugin() {}
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) final
|
||||
int HandleRequest(const RouteParameters &routeParameters, JSON::Object &json_result) final
|
||||
{
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
JSON::Object json_result;
|
||||
std::string temp_string;
|
||||
json_result.values["title"] = "Hello World";
|
||||
|
||||
@ -96,8 +94,7 @@ class HelloWorldPlugin final : public BasePlugin
|
||||
++counter;
|
||||
}
|
||||
json_result.values["hints"] = json_hints;
|
||||
|
||||
JSON::render(reply.content, json_result);
|
||||
return 200;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -30,10 +30,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "plugin_base.hpp"
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/string_util.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
// locates the nearest node in the road network for a given coordinate.
|
||||
@ -43,16 +44,14 @@ template <class DataFacadeT> class LocatePlugin final : public BasePlugin
|
||||
explicit LocatePlugin(DataFacadeT *facade) : descriptor_string("locate"), facade(facade) {}
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||
int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final
|
||||
{
|
||||
// check number of parameters
|
||||
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
return 400;
|
||||
}
|
||||
|
||||
JSON::Object json_result;
|
||||
FixedPointCoordinate result;
|
||||
if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
|
||||
result))
|
||||
@ -61,15 +60,13 @@ template <class DataFacadeT> class LocatePlugin final : public BasePlugin
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.status = http::Reply::ok;
|
||||
json_result.values["status"] = 0;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(result.lat / COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(result.lon / COORDINATE_PRECISION);
|
||||
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||
}
|
||||
|
||||
JSON::render(reply.content, json_result);
|
||||
return 200;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -30,11 +30,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "plugin_base.hpp"
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../data_structures/phantom_node.hpp"
|
||||
#include "../Util/integer_range.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
@ -48,13 +49,12 @@ template <class DataFacadeT> class NearestPlugin final : public BasePlugin
|
||||
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||
int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final
|
||||
{
|
||||
// check number of parameters
|
||||
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().is_valid())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
return 400;
|
||||
}
|
||||
auto number_of_results = static_cast<std::size_t>(route_parameters.num_results);
|
||||
std::vector<PhantomNode> phantom_node_vector;
|
||||
@ -62,14 +62,13 @@ template <class DataFacadeT> class NearestPlugin final : public BasePlugin
|
||||
phantom_node_vector,
|
||||
static_cast<int>(number_of_results));
|
||||
|
||||
JSON::Object json_result;
|
||||
if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid())
|
||||
{
|
||||
json_result.values["status"] = 207;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.status = http::Reply::ok;
|
||||
// reply.status = http::Reply::ok;
|
||||
json_result.values["status"] = 0;
|
||||
|
||||
if (number_of_results > 1)
|
||||
@ -106,7 +105,7 @@ template <class DataFacadeT> class NearestPlugin final : public BasePlugin
|
||||
json_result.values["name"] = temp_string;
|
||||
}
|
||||
}
|
||||
JSON::render(reply.content, json_result);
|
||||
return 200;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef BASEPLUGIN_H_
|
||||
#define BASEPLUGIN_H_
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
#include <osrm/json_container.hpp>
|
||||
#include <osrm/route_parameters.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -42,8 +42,8 @@ class BasePlugin
|
||||
// Maybe someone can explain the pure virtual destructor thing to me (dennis)
|
||||
virtual ~BasePlugin() {}
|
||||
virtual const std::string GetDescriptor() const = 0;
|
||||
virtual void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply) = 0;
|
||||
virtual bool check_all_coordinates(const std::vector<FixedPointCoordinate> coordinates) const final
|
||||
virtual int HandleRequest(const RouteParameters &, JSON::Object &) = 0;
|
||||
virtual bool check_all_coordinates(const std::vector<FixedPointCoordinate> &coordinates) const final
|
||||
{
|
||||
if (2 > coordinates.size() ||
|
||||
std::any_of(std::begin(coordinates),
|
||||
|
@ -30,9 +30,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "plugin_base.hpp"
|
||||
|
||||
#include "../data_structures/json_container.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
template <class DataFacadeT> class TimestampPlugin final : public BasePlugin
|
||||
@ -43,14 +44,12 @@ template <class DataFacadeT> class TimestampPlugin final : public BasePlugin
|
||||
{
|
||||
}
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||
int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final
|
||||
{
|
||||
reply.status = http::Reply::ok;
|
||||
JSON::Object json_result;
|
||||
json_result.values["status"] = 0;
|
||||
const std::string timestamp = facade->GetTimestamp();
|
||||
json_result.values["timestamp"] = timestamp;
|
||||
JSON::render(reply.content, json_result);
|
||||
return 200;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -40,6 +40,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../Util/make_unique.hpp"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/json_container.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
@ -69,14 +71,12 @@ template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
||||
|
||||
const std::string GetDescriptor() const final { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply) final
|
||||
int HandleRequest(const RouteParameters &route_parameters, JSON::Object &json_result) final
|
||||
{
|
||||
if (!check_all_coordinates(route_parameters.coordinates))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
return 400;
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
std::vector<phantom_node_pair> phantom_node_pair_list(route_parameters.coordinates.size());
|
||||
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
||||
@ -143,7 +143,7 @@ template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
||||
swap_phantom_from_big_cc_into_front);
|
||||
}
|
||||
|
||||
RawRouteData raw_route;
|
||||
InternalRouteResult raw_route;
|
||||
auto build_phantom_pairs =
|
||||
[&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair)
|
||||
{
|
||||
@ -183,7 +183,8 @@ template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
||||
}
|
||||
|
||||
descriptor->SetConfig(route_parameters);
|
||||
descriptor->Run(raw_route, reply);
|
||||
descriptor->Run(raw_route, json_result);
|
||||
return 200;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -78,7 +78,7 @@ template <class DataFacadeT> class AlternativeRouting final : private BasicRouti
|
||||
|
||||
virtual ~AlternativeRouting() {}
|
||||
|
||||
void operator()(const PhantomNodes &phantom_node_pair, RawRouteData &raw_route_data)
|
||||
void operator()(const PhantomNodes &phantom_node_pair, InternalRouteResult &raw_route_data)
|
||||
{
|
||||
std::vector<NodeID> alternative_path;
|
||||
std::vector<NodeID> via_node_candidate_list;
|
||||
|
@ -28,10 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef ROUTING_BASE_HPP
|
||||
#define ROUTING_BASE_HPP
|
||||
|
||||
#include "../data_structures/raw_route_data.hpp"
|
||||
#include "../data_structures/internal_route_result.hpp"
|
||||
#include "../data_structures/search_engine_data.hpp"
|
||||
#include "../data_structures/turn_instructions.hpp"
|
||||
// #include "../Util/simple_logger.hpp.h"
|
||||
// #include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
|
@ -51,7 +51,7 @@ template <class DataFacadeT> class ShortestPathRouting final : public BasicRouti
|
||||
|
||||
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
const std::vector<bool> &uturn_indicators,
|
||||
RawRouteData &raw_route_data) const
|
||||
InternalRouteResult &raw_route_data) const
|
||||
{
|
||||
int distance1 = 0;
|
||||
int distance2 = 0;
|
||||
|
@ -44,7 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <gdal/ogrsf_frmts.h>
|
||||
#endif
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
|
@ -27,37 +27,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/git_sha.hpp"
|
||||
#include "../Util/json_renderer.hpp"
|
||||
#include "../Util/ProgramOptions.h"
|
||||
#include "../Util/simple_logger.hpp"
|
||||
|
||||
#include <osrm/Reply.h>
|
||||
#include <osrm/RouteParameters.h>
|
||||
#include <osrm/ServerPaths.h>
|
||||
#include <osrm/json_container.hpp>
|
||||
#include <osrm/route_parameters.hpp>
|
||||
#include <osrm/server_paths.hpp>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
// Dude, real recursions on the OS stack? You must be brave...
|
||||
void print_tree(boost::property_tree::ptree const &property_tree, const unsigned recursion_depth)
|
||||
{
|
||||
auto end = property_tree.end();
|
||||
for (auto tree_iterator = property_tree.begin(); tree_iterator != end; ++tree_iterator)
|
||||
{
|
||||
for (unsigned current_recursion = 0; current_recursion < recursion_depth;
|
||||
++current_recursion)
|
||||
{
|
||||
std::cout << " " << std::flush;
|
||||
}
|
||||
std::cout << tree_iterator->first << ": " << tree_iterator->second.get_value<std::string>()
|
||||
<< std::endl;
|
||||
print_tree(tree_iterator->second, recursion_depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
@ -68,7 +46,6 @@ int main(int argc, const char *argv[])
|
||||
int ip_port, requested_thread_num;
|
||||
bool use_shared_memory = false, trial_run = false;
|
||||
ServerPaths server_paths;
|
||||
|
||||
const unsigned init_result = GenerateServerProgramOptions(argc,
|
||||
argv,
|
||||
server_paths,
|
||||
@ -78,11 +55,14 @@ int main(int argc, const char *argv[])
|
||||
use_shared_memory,
|
||||
trial_run);
|
||||
|
||||
if (init_result == INIT_FAILED)
|
||||
if (init_result == INIT_OK_DO_NOT_START_ENGINE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (init_result == INIT_FAILED)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
SimpleLogger().Write() << "starting up engines, " << g_GIT_DESCRIPTION;
|
||||
|
||||
OSRM routing_machine(server_paths, use_shared_memory);
|
||||
@ -93,7 +73,7 @@ int main(int argc, const char *argv[])
|
||||
route_parameters.alternate_route = true; // get an alternate route, too
|
||||
route_parameters.geometry = true; // retrieve geometry of route
|
||||
route_parameters.compression = true; // polyline encoding
|
||||
route_parameters.check_sum = UINT_MAX; // see wiki
|
||||
route_parameters.check_sum = -1; // see wiki
|
||||
route_parameters.service = "viaroute"; // that's routing
|
||||
route_parameters.output_format = "json";
|
||||
route_parameters.jsonp_parameter = ""; // set for jsonp wrapping
|
||||
@ -106,23 +86,10 @@ int main(int argc, const char *argv[])
|
||||
// target_coordinate
|
||||
route_parameters.coordinates.emplace_back(52.513191 * COORDINATE_PRECISION,
|
||||
13.415852 * COORDINATE_PRECISION);
|
||||
http::Reply osrm_reply;
|
||||
routing_machine.RunQuery(route_parameters, osrm_reply);
|
||||
|
||||
// attention: super-inefficient hack below:
|
||||
|
||||
std::stringstream my_stream;
|
||||
for (const auto &element : osrm_reply.content)
|
||||
{
|
||||
std::cout << element;
|
||||
my_stream << element;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
boost::property_tree::ptree property_tree;
|
||||
boost::property_tree::read_json(my_stream, property_tree);
|
||||
|
||||
print_tree(property_tree, 0);
|
||||
JSON::Object json_result;
|
||||
const int result_code = routing_machine.RunQuery(route_parameters, json_result);
|
||||
SimpleLogger().Write() << "http code: " << result_code;
|
||||
JSON::render(SimpleLogger().Write(), json_result);
|
||||
}
|
||||
catch (std::exception ¤t_exception)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user