#ifndef NEAREST_HPP #define NEAREST_HPP #include "engine/plugins/plugin_base.hpp" #include "engine/phantom_node.hpp" #include "util/integer_range.hpp" #include "osrm/json_container.hpp" #include namespace osrm { namespace engine { namespace plugins { /* * This Plugin locates the nearest point on a street in the road network for a given coordinate. */ class NearestPlugin final : public BasePlugin { public: explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest") {} const std::string GetDescriptor() const override final { return descriptor_string; } Status HandleRequest(const RouteParameters &route_parameters, util::json::Object &json_result) override final { // check number of parameters if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().IsValid()) { return Status::Error; } const auto &input_bearings = route_parameters.bearings; if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) { json_result.values["status_message"] = "Number of bearings does not match number of coordinates"; return Status::Error; } auto number_of_results = static_cast(route_parameters.num_results); const int bearing = input_bearings.size() > 0 ? input_bearings.front().first : 0; const int range = input_bearings.size() > 0 ? (input_bearings.front().second ? *input_bearings.front().second : 10) : 180; auto phantom_node_vector = facade->NearestPhantomNodes(route_parameters.coordinates.front(), number_of_results, bearing, range); if (phantom_node_vector.empty()) { json_result.values["status_message"] = std::string("Could not find a matching segments for coordinate"); return Status::NoSegment; } else { json_result.values["status_message"] = "Found nearest edge"; if (number_of_results > 1) { util::json::Array results; auto vector_length = phantom_node_vector.size(); for (const auto i : util::irange(0, std::min(number_of_results, vector_length))) { const auto &node = phantom_node_vector[i].phantom_node; util::json::Array json_coordinate; util::json::Object result; json_coordinate.values.push_back(node.location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back(node.location.lon / COORDINATE_PRECISION); result.values["mapped coordinate"] = json_coordinate; result.values["name"] = facade->get_name_for_id(node.name_id); results.values.push_back(result); } json_result.values["results"] = results; } else { util::json::Array json_coordinate; json_coordinate.values.push_back( phantom_node_vector.front().phantom_node.location.lat / COORDINATE_PRECISION); json_coordinate.values.push_back( phantom_node_vector.front().phantom_node.location.lon / COORDINATE_PRECISION); json_result.values["mapped_coordinate"] = json_coordinate; json_result.values["name"] = facade->get_name_for_id(phantom_node_vector.front().phantom_node.name_id); } } return Status::Ok; } private: DataFacadeT *facade; std::string descriptor_string; }; } } } #endif /* NEAREST_HPP */