#ifndef ENGINE_API_TRIP_HPP #define ENGINE_API_TRIP_HPP #include "engine/api/route_api.hpp" #include "engine/api/trip_parameters.hpp" #include "engine/datafacade/datafacade_base.hpp" #include "engine/internal_route_result.hpp" #include "util/integer_range.hpp" namespace osrm { namespace engine { namespace api { class TripAPI final : public RouteAPI { public: TripAPI(const datafacade::BaseDataFacade &facade_, const TripParameters ¶meters_) : RouteAPI(facade_, parameters_), parameters(parameters_) { } void MakeResponse(const std::vector> &sub_trips, const std::vector &sub_routes, const std::vector &phantoms, osrm::engine::api::ResultT &response) const { BOOST_ASSERT(sub_trips.size() == sub_routes.size()); if (response.is()) { auto &fb_result = response.get(); MakeResponse(sub_trips, sub_routes, phantoms, fb_result); } else { auto &json_result = response.get(); MakeResponse(sub_trips, sub_routes, phantoms, json_result); } } void MakeResponse(const std::vector> &sub_trips, const std::vector &sub_routes, const std::vector &phantoms, flatbuffers::FlatBufferBuilder &fb_result) const { auto data_timestamp = facade.GetTimestamp(); flatbuffers::Offset data_version_string; if (!data_timestamp.empty()) { data_version_string = fb_result.CreateString(data_timestamp); } auto response = MakeFBResponse(sub_routes, fb_result, [this, &fb_result, &sub_trips, &phantoms]() { return MakeWaypoints(fb_result, sub_trips, phantoms); }); if (!data_timestamp.empty()) { response->add_data_version(data_version_string); } fb_result.Finish(response->Finish()); } void MakeResponse(const std::vector> &sub_trips, const std::vector &sub_routes, const std::vector &phantoms, util::json::Object &response) const { auto number_of_routes = sub_trips.size(); util::json::Array routes; routes.values.reserve(number_of_routes); for (auto index : util::irange(0UL, sub_trips.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); routes.values.push_back(std::move(route)); } if (!parameters.skip_waypoints) { response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); } response.values["trips"] = std::move(routes); response.values["code"] = "Ok"; } protected: // FIXME this logic is a little backwards. We should change the output format of the // trip plugin routing algorithm to be easier to consume here. struct TripIndex { TripIndex() = default; TripIndex(unsigned sub_trip_index_, unsigned point_index_) : sub_trip_index(sub_trip_index_), point_index(point_index_) { } unsigned sub_trip_index = std::numeric_limits::max(); unsigned point_index = std::numeric_limits::max(); bool NotUsed() { return sub_trip_index == std::numeric_limits::max() && point_index == std::numeric_limits::max(); } }; flatbuffers::Offset>> MakeWaypoints(flatbuffers::FlatBufferBuilder &fb_result, const std::vector> &sub_trips, const std::vector &phantoms) const { std::vector> waypoints; waypoints.reserve(parameters.coordinates.size()); auto input_idx_to_trip_idx = MakeTripIndices(sub_trips); for (auto input_index : util::irange(0UL, parameters.coordinates.size())) { auto trip_index = input_idx_to_trip_idx[input_index]; BOOST_ASSERT(!trip_index.NotUsed()); auto waypoint = BaseAPI::MakeWaypoint(&fb_result, phantoms[input_index]); waypoint->add_waypoint_index(trip_index.point_index); waypoint->add_trips_index(trip_index.sub_trip_index); waypoints.push_back(waypoint->Finish()); } return fb_result.CreateVector(waypoints); } util::json::Array MakeWaypoints(const std::vector> &sub_trips, const std::vector &phantoms) const { util::json::Array waypoints; waypoints.values.reserve(parameters.coordinates.size()); auto input_idx_to_trip_idx = MakeTripIndices(sub_trips); for (auto input_index : util::irange(0UL, parameters.coordinates.size())) { auto trip_index = input_idx_to_trip_idx[input_index]; BOOST_ASSERT(!trip_index.NotUsed()); auto waypoint = BaseAPI::MakeWaypoint(phantoms[input_index]); waypoint.values["trips_index"] = trip_index.sub_trip_index; waypoint.values["waypoint_index"] = trip_index.point_index; waypoints.values.push_back(std::move(waypoint)); } return waypoints; } std::vector MakeTripIndices(const std::vector> &sub_trips) const { std::vector input_idx_to_trip_idx(parameters.coordinates.size()); for (auto sub_trip_index : util::irange(0u, sub_trips.size())) { for (auto point_index : util::irange(0u, sub_trips[sub_trip_index].size())) { input_idx_to_trip_idx[sub_trips[sub_trip_index][point_index]] = TripIndex{sub_trip_index, point_index}; } } return input_idx_to_trip_idx; } const TripParameters ¶meters; }; } // ns api } // ns engine } // ns osrm #endif