diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index 33a9940e2..860a945c4 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -39,7 +39,8 @@ class MatchAPI final : public RouteAPI 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); + sub_routes[index].target_traversed_in_reverse, + nullptr); route.values["confidence"] = sub_matchings[index].confidence; routes.values.push_back(std::move(route)); } @@ -62,7 +63,7 @@ class MatchAPI final : public RouteAPI { MatchingIndex() = default; MatchingIndex(unsigned sub_matching_index_, unsigned point_index_) - : sub_matching_index(sub_matching_index_), point_index(point_index_) + : sub_matching_index(sub_matching_index_), point_index(point_index_) { } diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 0838a7368..860aab231 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -16,8 +16,11 @@ #include "engine/internal_route_result.hpp" +#include "util/coordinate.hpp" #include "util/integer_range.hpp" +#include + namespace osrm { namespace engine @@ -33,21 +36,24 @@ class RouteAPI : public BaseAPI { } - void MakeResponse(const InternalRouteResult &raw_route, util::json::Object &response) const + void MakeResponse(const InternalRouteResult &raw_route, + util::json::Object &response, + const std::vector *const locations) const { auto number_of_routes = raw_route.has_alternative() ? 2UL : 1UL; util::json::Array routes; routes.values.resize(number_of_routes); routes.values[0] = MakeRoute(raw_route.segment_end_coordinates, raw_route.unpacked_path_segments, - raw_route.source_traversed_in_reverse, raw_route.target_traversed_in_reverse); + raw_route.source_traversed_in_reverse, raw_route.target_traversed_in_reverse, + locations); if (raw_route.has_alternative()) { std::vector> wrapped_leg(1); wrapped_leg.front() = std::move(raw_route.unpacked_alternative); routes.values[1] = MakeRoute(raw_route.segment_end_coordinates, wrapped_leg, raw_route.alt_source_traversed_in_reverse, - raw_route.alt_target_traversed_in_reverse); + raw_route.alt_target_traversed_in_reverse, locations); } response.values["waypoints"] = BaseAPI::MakeWaypoints(raw_route.segment_end_coordinates); response.values["routes"] = std::move(routes); @@ -70,7 +76,8 @@ class RouteAPI : public BaseAPI util::json::Object MakeRoute(const std::vector &segment_end_coordinates, std::vector> unpacked_path_segments, const std::vector &source_traversed_in_reverse, - const std::vector &target_traversed_in_reverse) const + const std::vector &target_traversed_in_reverse, + const std::vector *const locations) const { std::vector legs; std::vector leg_geometries; @@ -78,7 +85,8 @@ class RouteAPI : public BaseAPI legs.reserve(number_of_legs); leg_geometries.reserve(number_of_legs); - unpacked_path_segments = guidance::postProcess( std::move(unpacked_path_segments) ); + unpacked_path_segments = guidance::postProcess(std::move(unpacked_path_segments)); + BOOST_ASSERT(locations.size() == number_of_legs + 1); for (auto idx : util::irange(0UL, number_of_legs)) { const auto &phantoms = segment_end_coordinates[idx]; @@ -95,9 +103,18 @@ class RouteAPI : public BaseAPI if (parameters.steps) { + const auto getLoc = [](const std::vector *const locations, + int idx) -> boost::optional + { + if (locations) + return (*locations)[idx]; + return {}; + }; leg.steps = guidance::assembleSteps( BaseAPI::facade, path_data, leg_geometry, phantoms.source_phantom, - phantoms.target_phantom, reversed_source, reversed_target); + phantoms.target_phantom, reversed_source, reversed_target, + getLoc(locations, idx), getLoc(locations, idx + 1)); + ; } leg_geometries.push_back(std::move(leg_geometry)); diff --git a/include/engine/api/trip_api.hpp b/include/engine/api/trip_api.hpp index 62dbf238a..fa1351eb5 100644 --- a/include/engine/api/trip_api.hpp +++ b/include/engine/api/trip_api.hpp @@ -28,7 +28,8 @@ class TripAPI final : public RouteAPI void MakeResponse(const std::vector> &sub_trips, const std::vector &sub_routes, const std::vector &phantoms, - util::json::Object &response) const + util::json::Object &response, + const std::vector> * const coordinates) const { auto number_of_routes = sub_trips.size(); util::json::Array routes; @@ -39,7 +40,8 @@ class TripAPI final : public RouteAPI 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); + sub_routes[index].target_traversed_in_reverse, + coordinates ? &((*coordinates)[index]) : nullptr); routes.values.push_back(std::move(route)); } response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index 39983679c..42ac53575 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -14,6 +14,7 @@ #include "extractor/travel_mode.hpp" #include +#include namespace osrm { @@ -45,10 +46,8 @@ inline StepManeuver stepManeuverFromGeometry(TurnInstruction instruction, return StepManeuver{turn_coordinate, pre_turn_bearing, post_turn_bearing, instruction, exit}; } - } - template std::vector assembleSteps(const DataFacadeT &facade, const std::vector &leg_data, @@ -56,7 +55,9 @@ std::vector assembleSteps(const DataFacadeT &facade, const PhantomNode &source_node, const PhantomNode &target_node, const bool source_traversed_in_reverse, - const bool target_traversed_in_reverse) + const bool target_traversed_in_reverse, + boost::optional source_location, + boost::optional target_location) { const auto source_duration = (source_traversed_in_reverse ? source_node.GetReverseWeightPlusOffset() @@ -77,12 +78,21 @@ std::vector assembleSteps(const DataFacadeT &facade, std::vector steps; steps.reserve(number_of_segments); + // TODO do computation based on distance and choose better next vertex + BOOST_ASSERT(leg_geometry.size() >= 4); // source, phantom, closest positions on way + const auto initial_modifier = + source_location + ? angleToDirectionModifier(util::coordinate_calculation::computeAngle( + source_location.get(), leg_geometry.locations[0], leg_geometry.locations[1])) + : DirectionModifier::UTurn; + auto segment_index = 0; if (leg_data.size() > 0) { - StepManeuver maneuver = detail::stepManeuverFromGeometry( - TurnInstruction{TurnType::Location, DirectionModifier::Straight}, leg_geometry, - segment_index, INVALID_EXIT_NR); + + StepManeuver maneuver = + detail::stepManeuverFromGeometry(TurnInstruction{TurnType::Location, initial_modifier}, + leg_geometry, segment_index, INVALID_EXIT_NR); // TODO fix this: it makes no sense // PathData saves the information we need of the segment _before_ the turn, @@ -119,23 +129,27 @@ std::vector assembleSteps(const DataFacadeT &facade, // x---*---*---*---z compressed edge // |-------| duration StepManeuver maneuver = {source_node.location, 0., 0., - TurnInstruction{TurnType::Location, DirectionModifier::Straight}, + TurnInstruction{TurnType::Location, initial_modifier}, INVALID_EXIT_NR}; - steps.push_back(RouteStep{ - source_node.name_id, facade.get_name_for_id(source_node.name_id), - target_duration - source_duration, leg_geometry.segment_distances[segment_index], - source_mode, std::move(maneuver), leg_geometry.FrontIndex(segment_index), - leg_geometry.BackIndex(segment_index) + 1}); + steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id), + target_duration - source_duration, + leg_geometry.segment_distances[segment_index], source_mode, + std::move(maneuver), leg_geometry.FrontIndex(segment_index), + leg_geometry.BackIndex(segment_index) + 1}); } BOOST_ASSERT(segment_index == number_of_segments - 1); + const auto final_modifier = + target_location ? angleToDirectionModifier(util::coordinate_calculation::computeAngle( + *(leg_geometry.locations.end() - 3), + *(leg_geometry.locations.end() - 1), target_location.get())) + : DirectionModifier::UTurn; // This step has length zero, the only reason we need it is the target location steps.push_back(RouteStep{ target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode, StepManeuver{target_node.location, 0., 0., - TurnInstruction{TurnType::Location, DirectionModifier::Straight}, - INVALID_EXIT_NR}, + TurnInstruction{TurnType::Location, final_modifier}, INVALID_EXIT_NR}, leg_geometry.locations.size(), leg_geometry.locations.size()}); return steps; diff --git a/include/engine/guidance/turn_instruction.hpp b/include/engine/guidance/turn_instruction.hpp index cd18d4afa..21db10a35 100644 --- a/include/engine/guidance/turn_instruction.hpp +++ b/include/engine/guidance/turn_instruction.hpp @@ -69,6 +69,16 @@ enum TurnType // at the moment we can support 32 turn types, without increasing Notification // Travel Mode Changes` }; +inline bool isValidModifier( const TurnType type, const DirectionModifier modifier ) +{ + if( type == TurnType::Location && + modifier != DirectionModifier::Left + && modifier != DirectionModifier::Straight + && modifier != DirectionModifier::Right ) + return false; + return true; +} + const constexpr char *turn_type_names[] = {"invalid", "no turn", "waypoint", diff --git a/src/engine/api/json_factory.cpp b/src/engine/api/json_factory.cpp index f052c3778..70e9a7e92 100644 --- a/src/engine/api/json_factory.cpp +++ b/src/engine/api/json_factory.cpp @@ -100,8 +100,9 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver) { util::json::Object step_maneuver; step_maneuver.values["type"] = detail::instructionTypeToString(maneuver.instruction.type); - step_maneuver.values["modifier"] = - detail::instructionModifierToString(maneuver.instruction.direction_modifier); + if( isValidModifier( maneuver.instruction.type, maneuver.instruction.direction_modifier ) + step_maneuver.values["modifier"] = + detail::instructionModifierToString(maneuver.instruction.direction_modifier); step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location); step_maneuver.values["bearing_before"] = maneuver.bearing_before; step_maneuver.values["bearing_after"] = maneuver.bearing_after; diff --git a/src/engine/plugins/trip.cpp b/src/engine/plugins/trip.cpp index fecab3461..01a7c6070 100644 --- a/src/engine/plugins/trip.cpp +++ b/src/engine/plugins/trip.cpp @@ -243,13 +243,18 @@ Status TripPlugin::HandleRequest(const api::TripParameters ¶meters, // compute all round trip routes std::vector routes; routes.reserve(trips.size()); - for (auto &trip : trips) + std::vector> ordered_coordinates; + ordered_coordinates.reserve(trips.size()); + for (const auto &trip : trips) { routes.push_back(ComputeRoute(snapped_phantoms, parameters, trip)); + ordered_coordinates.push_back( std::vector() ); + for( const auto nid : trip ) + ordered_coordinates.back().push_back( parameters.coordinates[nid] ); } api::TripAPI trip_api{BasePlugin::facade, parameters}; - trip_api.MakeResponse(trips, routes, snapped_phantoms, json_result); + trip_api.MakeResponse(trips, routes, snapped_phantoms, json_result, &ordered_coordinates); return Status::Ok; } diff --git a/src/engine/plugins/viaroute.cpp b/src/engine/plugins/viaroute.cpp index f558a26c7..333923bba 100644 --- a/src/engine/plugins/viaroute.cpp +++ b/src/engine/plugins/viaroute.cpp @@ -87,7 +87,7 @@ Status ViaRoutePlugin::HandleRequest(const api::RouteParameters &route_parameter if (raw_route.is_valid()) { api::RouteAPI route_api{BasePlugin::facade, route_parameters}; - route_api.MakeResponse(raw_route, json_result); + route_api.MakeResponse(raw_route, json_result, &route_parameters.coordinates); } else {