1 #ifndef ENGINE_API_TRIP_HPP 2 #define ENGINE_API_TRIP_HPP 3 4 #include "engine/api/route_api.hpp" 5 #include "engine/api/trip_parameters.hpp" 6 7 #include "engine/datafacade/datafacade_base.hpp" 8 9 #include "engine/internal_route_result.hpp" 10 11 #include "util/integer_range.hpp" 12 13 namespace osrm 14 { 15 namespace engine 16 { 17 namespace api 18 { 19 20 class TripAPI final : public RouteAPI 21 { 22 public: TripAPI(const datafacade::BaseDataFacade & facade_,const TripParameters & parameters_)23 TripAPI(const datafacade::BaseDataFacade &facade_, const TripParameters ¶meters_) 24 : RouteAPI(facade_, parameters_), parameters(parameters_) 25 { 26 } MakeResponse(const std::vector<std::vector<NodeID>> & sub_trips,const std::vector<InternalRouteResult> & sub_routes,const std::vector<PhantomNode> & phantoms,osrm::engine::api::ResultT & response) const27 void MakeResponse(const std::vector<std::vector<NodeID>> &sub_trips, 28 const std::vector<InternalRouteResult> &sub_routes, 29 const std::vector<PhantomNode> &phantoms, 30 osrm::engine::api::ResultT &response) const 31 { 32 BOOST_ASSERT(sub_trips.size() == sub_routes.size()); 33 34 if (response.is<flatbuffers::FlatBufferBuilder>()) 35 { 36 auto &fb_result = response.get<flatbuffers::FlatBufferBuilder>(); 37 MakeResponse(sub_trips, sub_routes, phantoms, fb_result); 38 } 39 else 40 { 41 auto &json_result = response.get<util::json::Object>(); 42 MakeResponse(sub_trips, sub_routes, phantoms, json_result); 43 } 44 } MakeResponse(const std::vector<std::vector<NodeID>> & sub_trips,const std::vector<InternalRouteResult> & sub_routes,const std::vector<PhantomNode> & phantoms,flatbuffers::FlatBufferBuilder & fb_result) const45 void MakeResponse(const std::vector<std::vector<NodeID>> &sub_trips, 46 const std::vector<InternalRouteResult> &sub_routes, 47 const std::vector<PhantomNode> &phantoms, 48 flatbuffers::FlatBufferBuilder &fb_result) const 49 { 50 auto data_timestamp = facade.GetTimestamp(); 51 flatbuffers::Offset<flatbuffers::String> data_version_string; 52 if (!data_timestamp.empty()) 53 { 54 data_version_string = fb_result.CreateString(data_timestamp); 55 } 56 57 auto response = 58 MakeFBResponse(sub_routes, fb_result, [this, &fb_result, &sub_trips, &phantoms]() { 59 return MakeWaypoints(fb_result, sub_trips, phantoms); 60 }); 61 62 if (!data_timestamp.empty()) 63 { 64 response->add_data_version(data_version_string); 65 } 66 fb_result.Finish(response->Finish()); 67 } MakeResponse(const std::vector<std::vector<NodeID>> & sub_trips,const std::vector<InternalRouteResult> & sub_routes,const std::vector<PhantomNode> & phantoms,util::json::Object & response) const68 void MakeResponse(const std::vector<std::vector<NodeID>> &sub_trips, 69 const std::vector<InternalRouteResult> &sub_routes, 70 const std::vector<PhantomNode> &phantoms, 71 util::json::Object &response) const 72 { 73 auto number_of_routes = sub_trips.size(); 74 util::json::Array routes; 75 routes.values.reserve(number_of_routes); 76 for (auto index : util::irange<std::size_t>(0UL, sub_trips.size())) 77 { 78 auto route = MakeRoute(sub_routes[index].segment_end_coordinates, 79 sub_routes[index].unpacked_path_segments, 80 sub_routes[index].source_traversed_in_reverse, 81 sub_routes[index].target_traversed_in_reverse); 82 routes.values.push_back(std::move(route)); 83 } 84 if (!parameters.skip_waypoints) 85 { 86 response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); 87 } 88 response.values["trips"] = std::move(routes); 89 response.values["code"] = "Ok"; 90 } 91 92 protected: 93 // FIXME this logic is a little backwards. We should change the output format of the 94 // trip plugin routing algorithm to be easier to consume here. 95 96 struct TripIndex 97 { 98 TripIndex() = default; 99 TripIndexosrm::engine::api::TripAPI::TripIndex100 TripIndex(unsigned sub_trip_index_, unsigned point_index_) 101 : sub_trip_index(sub_trip_index_), point_index(point_index_) 102 { 103 } 104 105 unsigned sub_trip_index = std::numeric_limits<unsigned>::max(); 106 unsigned point_index = std::numeric_limits<unsigned>::max(); 107 NotUsedosrm::engine::api::TripAPI::TripIndex108 bool NotUsed() 109 { 110 return sub_trip_index == std::numeric_limits<unsigned>::max() && 111 point_index == std::numeric_limits<unsigned>::max(); 112 } 113 }; 114 115 flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<fbresult::Waypoint>>> MakeWaypoints(flatbuffers::FlatBufferBuilder & fb_result,const std::vector<std::vector<NodeID>> & sub_trips,const std::vector<PhantomNode> & phantoms) const116 MakeWaypoints(flatbuffers::FlatBufferBuilder &fb_result, 117 const std::vector<std::vector<NodeID>> &sub_trips, 118 const std::vector<PhantomNode> &phantoms) const 119 { 120 std::vector<flatbuffers::Offset<fbresult::Waypoint>> waypoints; 121 waypoints.reserve(parameters.coordinates.size()); 122 123 auto input_idx_to_trip_idx = MakeTripIndices(sub_trips); 124 125 for (auto input_index : util::irange<std::size_t>(0UL, parameters.coordinates.size())) 126 { 127 auto trip_index = input_idx_to_trip_idx[input_index]; 128 BOOST_ASSERT(!trip_index.NotUsed()); 129 130 auto waypoint = BaseAPI::MakeWaypoint(&fb_result, phantoms[input_index]); 131 waypoint->add_waypoint_index(trip_index.point_index); 132 waypoint->add_trips_index(trip_index.sub_trip_index); 133 waypoints.push_back(waypoint->Finish()); 134 } 135 136 return fb_result.CreateVector(waypoints); 137 } 138 MakeWaypoints(const std::vector<std::vector<NodeID>> & sub_trips,const std::vector<PhantomNode> & phantoms) const139 util::json::Array MakeWaypoints(const std::vector<std::vector<NodeID>> &sub_trips, 140 const std::vector<PhantomNode> &phantoms) const 141 { 142 util::json::Array waypoints; 143 waypoints.values.reserve(parameters.coordinates.size()); 144 145 auto input_idx_to_trip_idx = MakeTripIndices(sub_trips); 146 147 for (auto input_index : util::irange<std::size_t>(0UL, parameters.coordinates.size())) 148 { 149 auto trip_index = input_idx_to_trip_idx[input_index]; 150 BOOST_ASSERT(!trip_index.NotUsed()); 151 152 auto waypoint = BaseAPI::MakeWaypoint(phantoms[input_index]); 153 waypoint.values["trips_index"] = trip_index.sub_trip_index; 154 waypoint.values["waypoint_index"] = trip_index.point_index; 155 waypoints.values.push_back(std::move(waypoint)); 156 } 157 158 return waypoints; 159 } 160 MakeTripIndices(const std::vector<std::vector<NodeID>> & sub_trips) const161 std::vector<TripIndex> MakeTripIndices(const std::vector<std::vector<NodeID>> &sub_trips) const 162 { 163 std::vector<TripIndex> input_idx_to_trip_idx(parameters.coordinates.size()); 164 for (auto sub_trip_index : util::irange<unsigned>(0u, sub_trips.size())) 165 { 166 for (auto point_index : util::irange<unsigned>(0u, sub_trips[sub_trip_index].size())) 167 { 168 input_idx_to_trip_idx[sub_trips[sub_trip_index][point_index]] = 169 TripIndex{sub_trip_index, point_index}; 170 } 171 } 172 return input_idx_to_trip_idx; 173 } 174 175 const TripParameters ¶meters; 176 }; 177 178 } // namespace api 179 } // namespace engine 180 } // namespace osrm 181 182 #endif 183