From 90191c9f345136dc7d355e12153ef6f95fe90e85 Mon Sep 17 00:00:00 2001 From: Denis Chaplygin Date: Thu, 8 Aug 2019 18:20:03 +0300 Subject: [PATCH] Added flatbuffers output support to the 'Match' service --- .../api/flatbuffers/fbresult_generated.h | 18 +- include/engine/api/flatbuffers/match.fbs | 2 +- include/engine/api/match_api.hpp | 163 ++++++++++++++---- src/engine/plugins/match.cpp | 3 +- src/server/service/match_service.cpp | 6 + 5 files changed, 144 insertions(+), 48 deletions(-) diff --git a/include/engine/api/flatbuffers/fbresult_generated.h b/include/engine/api/flatbuffers/fbresult_generated.h index cfea1f295..d5584704f 100644 --- a/include/engine/api/flatbuffers/fbresult_generated.h +++ b/include/engine/api/flatbuffers/fbresult_generated.h @@ -1628,7 +1628,7 @@ flatbuffers::Offset CreateRoute(flatbuffers::FlatBufferBuilder &_fbb, con struct MatchT : public flatbuffers::NativeTable { typedef Match TableType; std::vector> tracepoints; - std::vector> matchings; + std::vector> matchings; MatchT() { } }; @@ -1642,8 +1642,8 @@ struct Match FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector> *tracepoints() const { return GetPointer> *>(VT_TRACEPOINTS); } - const flatbuffers::Vector> *matchings() const { - return GetPointer> *>(VT_MATCHINGS); + const flatbuffers::Vector> *matchings() const { + return GetPointer> *>(VT_MATCHINGS); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && @@ -1666,7 +1666,7 @@ struct MatchBuilder { void add_tracepoints(flatbuffers::Offset>> tracepoints) { fbb_.AddOffset(Match::VT_TRACEPOINTS, tracepoints); } - void add_matchings(flatbuffers::Offset>> matchings) { + void add_matchings(flatbuffers::Offset>> matchings) { fbb_.AddOffset(Match::VT_MATCHINGS, matchings); } explicit MatchBuilder(flatbuffers::FlatBufferBuilder &_fbb) @@ -1684,7 +1684,7 @@ struct MatchBuilder { inline flatbuffers::Offset CreateMatch( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset>> tracepoints = 0, - flatbuffers::Offset>> matchings = 0) { + flatbuffers::Offset>> matchings = 0) { MatchBuilder builder_(_fbb); builder_.add_matchings(matchings); builder_.add_tracepoints(tracepoints); @@ -1694,9 +1694,9 @@ inline flatbuffers::Offset CreateMatch( inline flatbuffers::Offset CreateMatchDirect( flatbuffers::FlatBufferBuilder &_fbb, const std::vector> *tracepoints = nullptr, - const std::vector> *matchings = nullptr) { + const std::vector> *matchings = nullptr) { auto tracepoints__ = tracepoints ? _fbb.CreateVector>(*tracepoints) : 0; - auto matchings__ = matchings ? _fbb.CreateVector>(*matchings) : 0; + auto matchings__ = matchings ? _fbb.CreateVector>(*matchings) : 0; return osrm::engine::api::fbresult::CreateMatch( _fbb, tracepoints__, @@ -2675,7 +2675,7 @@ inline void Match::UnPackTo(MatchT *_o, const flatbuffers::resolver_function_t * (void)_o; (void)_resolver; { auto _e = tracepoints(); if (_e) { _o->tracepoints.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->tracepoints[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } }; - { auto _e = matchings(); if (_e) { _o->matchings.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->matchings[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } }; + { auto _e = matchings(); if (_e) { _o->matchings.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->matchings[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } }; } inline flatbuffers::Offset Match::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MatchT* _o, const flatbuffers::rehasher_function_t *_rehasher) { @@ -2687,7 +2687,7 @@ inline flatbuffers::Offset CreateMatch(flatbuffers::FlatBufferBuilder &_f (void)_o; struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MatchT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _tracepoints = _o->tracepoints.size() ? _fbb.CreateVector> (_o->tracepoints.size(), [](size_t i, _VectorArgs *__va) { return CreateWaypoint(*__va->__fbb, __va->__o->tracepoints[i].get(), __va->__rehasher); }, &_va ) : 0; - auto _matchings = _o->matchings.size() ? _fbb.CreateVector> (_o->matchings.size(), [](size_t i, _VectorArgs *__va) { return CreateRoute(*__va->__fbb, __va->__o->matchings[i].get(), __va->__rehasher); }, &_va ) : 0; + auto _matchings = _o->matchings.size() ? _fbb.CreateVector> (_o->matchings.size(), [](size_t i, _VectorArgs *__va) { return CreateRouteObject(*__va->__fbb, __va->__o->matchings[i].get(), __va->__rehasher); }, &_va ) : 0; return osrm::engine::api::fbresult::CreateMatch( _fbb, _tracepoints, diff --git a/include/engine/api/flatbuffers/match.fbs b/include/engine/api/flatbuffers/match.fbs index e4a26fe37..62356d3d1 100644 --- a/include/engine/api/flatbuffers/match.fbs +++ b/include/engine/api/flatbuffers/match.fbs @@ -3,5 +3,5 @@ namespace osrm.engine.api.fbresult; table Match { tracepoints: [Waypoint]; - matchings: [Route]; + matchings: [RouteObject]; } \ No newline at end of file diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index 86a96c65b..a88b3b84c 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -29,6 +29,42 @@ class MatchAPI final : public RouteAPI { } + void MakeResponse(const std::vector &sub_matchings, + const std::vector &sub_routes, + osrm::engine::api::ResultT &response) const + { + BOOST_ASSERT(sub_matchings.size() == sub_routes.size()); + if (response.is()) { + auto &fb_result = response.get(); + MakeResponse(sub_matchings, sub_routes, fb_result); + } else { + auto &json_result = response.get(); + MakeResponse(sub_matchings, sub_routes, json_result); + } + } + void MakeResponse(const std::vector &sub_matchings, + const std::vector &sub_routes, + flatbuffers::FlatBufferBuilder &fb_result) const + { + fbresult::FBResultBuilder response(fb_result); + fbresult::MatchBuilder match(fb_result); + + std::vector> routes; + routes.reserve(sub_matchings.size()); + for (auto index : util::irange(0UL, sub_matchings.size())) + { + routes.push_back(MakeRoute(fb_result, + 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)); + } + match.add_matchings(fb_result.CreateVector(routes)); + match.add_tracepoints(fb_result.CreateVector(MakeTracepoints(fb_result, sub_matchings))); + + response.add_match(match.Finish()); + fb_result.Finish(response.Finish()); + } void MakeResponse(const std::vector &sub_matchings, const std::vector &sub_routes, util::json::Object &response) const @@ -36,7 +72,6 @@ class MatchAPI final : public RouteAPI 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, @@ -55,47 +90,84 @@ class MatchAPI final : public RouteAPI // 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. + 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> + MakeTracepoints(flatbuffers::FlatBufferBuilder &fb_result, const std::vector &sub_matchings) const + { + std::vector> waypoints; + waypoints.reserve(parameters.coordinates.size()); + + auto trace_idx_to_matching_idx = MakeMatchingIndices(sub_matchings); + + BOOST_ASSERT(parameters.waypoints.empty() || sub_matchings.size() == 1); + + std::size_t was_waypoint_idx = 0; + for (auto trace_index : util::irange(0UL, parameters.coordinates.size())) + { + + if (tidy_result.can_be_removed[trace_index]) + { + waypoints.push_back(fbresult::WaypointBuilder(fb_result).Finish()); + continue; + } + auto matching_index = trace_idx_to_matching_idx[trace_index]; + if (matching_index.NotMatched()) + { + waypoints.push_back(fbresult::WaypointBuilder(fb_result).Finish()); + continue; + } + const auto &phantom = + sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index]; + auto waypoint = BaseAPI::MakeWaypoint(fb_result, phantom); + waypoint.add_matchings_index(matching_index.sub_matching_index); + waypoint.add_alternatives_count(sub_matchings[matching_index.sub_matching_index] + .alternatives_count[matching_index.point_index]); + // waypoint indices need to be adjusted if route legs were collapsed + // waypoint parameter assumes there is only one match object + if (!parameters.waypoints.empty()) + { + if (tidy_result.was_waypoint[trace_index]) + { + waypoint.add_waypoint_index(was_waypoint_idx); + was_waypoint_idx++; + } + else + { + waypoint.add_waypoint_index(0); + } + } else { + waypoint.add_waypoint_index(matching_index.point_index); + } + waypoints.push_back(waypoint.Finish()); + } + + return waypoints; + } + 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()))) - { - // tidied_to_original: index of the input coordinate that a tidied coordinate - // corresponds to. - // sub_matching indices: index of the coordinate passed to map matching plugin that - // a matched node corresponds to. - trace_idx_to_matching_idx[tidy_result - .tidied_to_original[sub_matchings[sub_matching_index] - .indices[point_index]]] = - MatchingIndex{sub_matching_index, point_index}; - } - } + auto trace_idx_to_matching_idx = MakeMatchingIndices(sub_matchings); BOOST_ASSERT(parameters.waypoints.empty() || sub_matchings.size() == 1); @@ -141,6 +213,25 @@ class MatchAPI final : public RouteAPI return waypoints; } + std::vector MakeMatchingIndices(const std::vector &sub_matchings) const { + 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()))) { + // tidied_to_original: index of the input coordinate that a tidied coordinate + // corresponds to. + // sub_matching indices: index of the coordinate passed to map matching plugin that + // a matched node corresponds to. + trace_idx_to_matching_idx[tidy_result + .tidied_to_original[sub_matchings[sub_matching_index] + .indices[point_index]]] = + MatchingIndex{sub_matching_index, point_index}; + } + } + return trace_idx_to_matching_idx; + } + const MatchParameters ¶meters; const tidy::Result &tidy_result; }; diff --git a/src/engine/plugins/match.cpp b/src/engine/plugins/match.cpp index 799ac4393..b64deeff0 100644 --- a/src/engine/plugins/match.cpp +++ b/src/engine/plugins/match.cpp @@ -114,7 +114,6 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, const api::MatchParameters ¶meters, osrm::engine::api::ResultT &result) const { - auto& json_result = result.get(); if (!algorithms.HasMapMatching()) { return Error("NotImplemented", @@ -314,7 +313,7 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, } api::MatchAPI match_api{facade, parameters, tidied}; - match_api.MakeResponse(sub_matchings, sub_routes, json_result); + match_api.MakeResponse(sub_matchings, sub_routes, result); return Status::Ok; } diff --git a/src/server/service/match_service.cpp b/src/server/service/match_service.cpp index 2918f11b0..3a5ea1753 100644 --- a/src/server/service/match_service.cpp +++ b/src/server/service/match_service.cpp @@ -68,6 +68,12 @@ MatchService::RunQuery(std::size_t prefix_length, std::string &query, osrm::engi } BOOST_ASSERT(parameters->IsValid()); + if (parameters->format) + { + if (parameters->format == engine::api::BaseParameters::OutputFormatType::FLATBUFFERS) { + result = flatbuffers::FlatBufferBuilder(); + } + } return BaseService::routing_machine.Match(*parameters, result); } }