#ifndef ENGINE_API_MATCH_HPP #define ENGINE_API_MATCH_HPP #include "engine/api/route_api.hpp" #include "engine/api/match_parameters.hpp" #include "engine/datafacade/datafacade_base.hpp" #include "engine/internal_route_result.hpp" #include "engine/map_matching/sub_matching.hpp" #include "util/integer_range.hpp" namespace osrm { namespace engine { namespace api { class MatchAPI final : public RouteAPI { public: MatchAPI(const datafacade::BaseDataFacade &facade_, const MatchParameters ¶meters_) : RouteAPI(facade_, parameters_), parameters(parameters_) { } void MakeResponse(const std::vector &sub_matchings, const std::vector &sub_routes, util::json::Object &response) const { auto number_of_routes = sub_matchings.size(); util::json::Array routes; routes.values.reserve(number_of_routes); BOOST_ASSERT(sub_matchings.size() == sub_routes.size()); for (auto index : util::irange(0UL, sub_matchings.size())) { auto route = MakeRoute(sub_routes[index].segment_end_coordinates, sub_routes[index].unpacked_path_segments, sub_routes[index].source_traversed_in_reverse, sub_routes[index].target_traversed_in_reverse); route.values["confidence"] = sub_matchings[index].confidence; routes.values.push_back(std::move(route)); } response.values["tracepoints"] = MakeTracepoints(sub_matchings); response.values["matchings"] = std::move(routes); response.values["code"] = "Ok"; } // FIXME gcc 4.8 doesn't support for lambdas to call protected member functions // protected: // FIXME this logic is a little backwards. We should change the output format of the // map_matching // routing algorithm to be easier to consume here. util::json::Array MakeTracepoints(const std::vector &sub_matchings) const { util::json::Array waypoints; waypoints.values.reserve(parameters.coordinates.size()); struct MatchingIndex { MatchingIndex() = default; MatchingIndex(unsigned sub_matching_index_, unsigned point_index_) : sub_matching_index(sub_matching_index_), point_index(point_index_) { } unsigned sub_matching_index = std::numeric_limits::max(); unsigned point_index = std::numeric_limits::max(); bool NotMatched() { return sub_matching_index == std::numeric_limits::max() && point_index == std::numeric_limits::max(); } }; std::vector trace_idx_to_matching_idx(parameters.coordinates.size()); for (auto sub_matching_index : util::irange(0u, static_cast(sub_matchings.size()))) { for (auto point_index : util::irange( 0u, static_cast(sub_matchings[sub_matching_index].indices.size()))) { trace_idx_to_matching_idx[sub_matchings[sub_matching_index].indices[point_index]] = MatchingIndex{sub_matching_index, point_index}; } } for (auto trace_index : util::irange(0UL, parameters.coordinates.size())) { auto matching_index = trace_idx_to_matching_idx[trace_index]; if (matching_index.NotMatched()) { waypoints.values.push_back(util::json::Null()); continue; } const auto &phantom = sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index]; auto waypoint = BaseAPI::MakeWaypoint(phantom); waypoint.values["matchings_index"] = matching_index.sub_matching_index; waypoint.values["waypoint_index"] = matching_index.point_index; waypoints.values.push_back(std::move(waypoint)); } return waypoints; } const MatchParameters ¶meters; }; } // ns api } // ns engine } // ns osrm #endif