#ifndef ENGINE_API_BASE_API_HPP #define ENGINE_API_BASE_API_HPP #include "engine/api/base_parameters.hpp" #include "engine/api/flatbuffers/fbresult_generated.h" #include "engine/datafacade/datafacade_base.hpp" #include "engine/api/json_factory.hpp" #include "engine/hint.hpp" #include "util/coordinate_calculation.hpp" #include #include #include #include #include #include #include namespace osrm::engine::api { static const constexpr char *INTERSECTION_DELIMITER = " / "; class BaseAPI { public: BaseAPI(const datafacade::BaseDataFacade &facade_, const BaseParameters ¶meters_) : facade(facade_), parameters(parameters_) { } util::json::Array MakeWaypoints(const std::vector &waypoint_candidates) const { BOOST_ASSERT(parameters.coordinates.size() > 0); BOOST_ASSERT(parameters.coordinates.size() == waypoint_candidates.size()); util::json::Array waypoints; waypoints.values.resize(parameters.coordinates.size()); boost::range::transform(waypoint_candidates, waypoints.values.begin(), [this](const PhantomNodeCandidates &candidates) { return MakeWaypoint(candidates); }); return waypoints; } // FIXME: gcc 4.9 does not like MakeWaypoints to be protected // protected: util::json::Object MakeWaypoint(const PhantomNodeCandidates &candidates) const { // TODO: check forward/reverse const auto toName = [this](const auto &phantom) { return std::string( facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))); }; const auto noEmpty = [](const auto &name) { return !name.empty(); }; // At an intersection we may have multiple phantom node candidates. // Combine them to represent the waypoint name. std::string waypoint_name = boost::algorithm::join( candidates | boost::adaptors::transformed(toName) | boost::adaptors::filtered(noEmpty), INTERSECTION_DELIMITER); const auto &snapped_location = candidatesSnappedLocation(candidates); const auto &input_location = candidatesInputLocation(candidates); if (parameters.generate_hints) { std::vector seg_hints(candidates.size()); std::transform(candidates.begin(), candidates.end(), seg_hints.begin(), [this](const auto &phantom) { return SegmentHint{phantom, facade.GetCheckSum()}; }); return json::makeWaypoint( snapped_location, util::coordinate_calculation::greatCircleDistance(snapped_location, input_location), waypoint_name, {std::move(seg_hints)}); } else { return json::makeWaypoint( snapped_location, util::coordinate_calculation::greatCircleDistance(snapped_location, input_location), waypoint_name); } } flatbuffers::Offset>> MakeWaypoints(flatbuffers::FlatBufferBuilder *builder, const std::vector &waypoint_candidates) const { BOOST_ASSERT(parameters.coordinates.size() > 0); BOOST_ASSERT(parameters.coordinates.size() == waypoint_candidates.size()); std::vector> waypoints; waypoints.resize(parameters.coordinates.size()); std::transform(waypoint_candidates.begin(), waypoint_candidates.end(), waypoints.begin(), [this, builder](const PhantomNodeCandidates &candidates) { return MakeWaypoint(builder, candidates)->Finish(); }); return builder->CreateVector(waypoints); } // FIXME: gcc 4.9 does not like MakeWaypoints to be protected // protected: std::unique_ptr MakeWaypoint(flatbuffers::FlatBufferBuilder *builder, const PhantomNodeCandidates &candidates) const { const auto &snapped_location = candidatesSnappedLocation(candidates); const auto &input_location = candidatesInputLocation(candidates); auto location = fbresult::Position( static_cast(static_cast(util::toFloating(snapped_location.lon))), static_cast(static_cast(util::toFloating(snapped_location.lat)))); const auto toName = [this](const auto &phantom) { return std::string( facade.GetNameForID(facade.GetNameIndex(phantom.forward_segment_id.id))); }; const auto noEmpty = [](const auto &name) { return !name.empty(); }; // At an intersection we may have multiple phantom node candidates. // Combine them to represent the waypoint name. std::string waypoint_name = boost::algorithm::join( candidates | boost::adaptors::transformed(toName) | boost::adaptors::filtered(noEmpty), INTERSECTION_DELIMITER); auto name_string = builder->CreateString(waypoint_name); flatbuffers::Offset hint_string; if (parameters.generate_hints) { std::vector seg_hints(candidates.size()); std::transform(candidates.begin(), candidates.end(), seg_hints.begin(), [this](const auto &phantom) { return SegmentHint{phantom, facade.GetCheckSum()}; }); Hint hint{std::move(seg_hints)}; hint_string = builder->CreateString(hint.ToBase64()); } auto waypoint = std::make_unique(*builder); waypoint->add_location(&location); waypoint->add_distance(static_cast( util::coordinate_calculation::greatCircleDistance(snapped_location, input_location))); waypoint->add_name(name_string); if (parameters.generate_hints) { waypoint->add_hint(hint_string); } return waypoint; } const datafacade::BaseDataFacade &facade; const BaseParameters ¶meters; }; } // namespace osrm::engine::api #endif