From f11ec73226775995b500a4ca31888f9b30bd0af5 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Tue, 8 Mar 2016 16:46:01 +0100 Subject: [PATCH] implements relative position feature based on coordinates --- include/engine/api/base_api.hpp | 19 +++--- include/engine/api/match_api.hpp | 2 +- include/engine/api/nearest_api.hpp | 3 +- include/engine/api/table_api.hpp | 27 ++++---- include/engine/api/trip_api.hpp | 11 ++- include/engine/geospatial_query.hpp | 20 +++--- include/engine/guidance/assemble_steps.hpp | 78 ++++++++++++++++------ include/engine/hint.hpp | 5 +- include/engine/phantom_node.hpp | 19 ++++-- 9 files changed, 114 insertions(+), 70 deletions(-) diff --git a/include/engine/api/base_api.hpp b/include/engine/api/base_api.hpp index 904c56478db..a16b931fa94 100644 --- a/include/engine/api/base_api.hpp +++ b/include/engine/api/base_api.hpp @@ -8,6 +8,7 @@ #include "engine/hint.hpp" #include +#include #include @@ -33,24 +34,22 @@ class BaseAPI util::json::Array waypoints; waypoints.values.resize(parameters.coordinates.size()); - waypoints.values[0] = MakeWaypoint(parameters.coordinates.front(), - segment_end_coordinates.front().source_phantom); + waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom); - auto coord_iter = std::next(parameters.coordinates.begin()); auto out_iter = std::next(waypoints.values.begin()); - for (const auto &phantoms : segment_end_coordinates) - { - *out_iter++ = MakeWaypoint(*coord_iter++, phantoms.target_phantom); - } + boost::range::transform(segment_end_coordinates, out_iter, + [this](const PhantomNodes &phantom_pair) + { + return MakeWaypoint(phantom_pair.target_phantom); + }); return waypoints; } protected: - util::json::Object MakeWaypoint(const util::Coordinate input_coordinate, - const PhantomNode &phantom) const + util::json::Object MakeWaypoint(const PhantomNode &phantom) const { return json::makeWaypoint(phantom.location, facade.get_name_for_id(phantom.name_id), - Hint{input_coordinate, phantom, facade.GetCheckSum()}); + Hint{phantom, facade.GetCheckSum()}); } const datafacade::BaseDataFacade &facade; diff --git a/include/engine/api/match_api.hpp b/include/engine/api/match_api.hpp index 15e62d46634..0b4d9e9d4f2 100644 --- a/include/engine/api/match_api.hpp +++ b/include/engine/api/match_api.hpp @@ -98,7 +98,7 @@ class MatchAPI final : public RouteAPI } const auto &phantom = sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index]; - auto waypoint = BaseAPI::MakeWaypoint(parameters.coordinates[trace_index], phantom); + auto waypoint = BaseAPI::MakeWaypoint(phantom); waypoint.values["matchings_index"] = matching_index.sub_matching_index; waypoint.values["waypoint_index"] = matching_index.point_index; waypoints.values.push_back(std::move(waypoint)); diff --git a/include/engine/api/nearest_api.hpp b/include/engine/api/nearest_api.hpp index 50cb1be1c40..ab3747efea2 100644 --- a/include/engine/api/nearest_api.hpp +++ b/include/engine/api/nearest_api.hpp @@ -38,8 +38,7 @@ class NearestAPI final : public BaseAPI waypoints.values.begin(), [this](const PhantomNodeWithDistance &phantom_with_distance) { - auto waypoint = MakeWaypoint(parameters.coordinates.front(), - phantom_with_distance.phantom_node); + auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node); waypoint.values["distance"] = phantom_with_distance.distance; return waypoint; }); diff --git a/include/engine/api/table_api.hpp b/include/engine/api/table_api.hpp index 4f29eb54092..59005026705 100644 --- a/include/engine/api/table_api.hpp +++ b/include/engine/api/table_api.hpp @@ -17,6 +17,8 @@ #include "util/integer_range.hpp" +#include + namespace osrm { namespace engine @@ -72,13 +74,12 @@ class TableAPI final : public BaseAPI util::json::Array json_waypoints; json_waypoints.values.reserve(phantoms.size()); BOOST_ASSERT(phantoms.size() == parameters.coordinates.size()); - auto phantom_iter = phantoms.begin(); - auto coordinate_iter = parameters.coordinates.begin(); - for (; phantom_iter != phantoms.end() && coordinate_iter != parameters.coordinates.end(); - ++phantom_iter, ++coordinate_iter) - { - json_waypoints.values.push_back(BaseAPI::MakeWaypoint(*coordinate_iter, *phantom_iter)); - } + + boost::range::transform(phantoms, std::back_inserter(json_waypoints.values), + [this](const PhantomNode &phantom) + { + return BaseAPI::MakeWaypoint(phantom); + }); return json_waypoints; } @@ -87,12 +88,12 @@ class TableAPI final : public BaseAPI { util::json::Array json_waypoints; json_waypoints.values.reserve(indices.size()); - for (auto idx : indices) - { - BOOST_ASSERT(idx < phantoms.size() && idx < parameters.coordinates.size()); - json_waypoints.values.push_back( - BaseAPI::MakeWaypoint(parameters.coordinates[idx], phantoms[idx])); - } + boost::range::transform(indices, std::back_inserter(json_waypoints.values), + [this, phantoms](const std::size_t idx) + { + BOOST_ASSERT(idx < phantoms.size()); + return BaseAPI::MakeWaypoint(phantoms[idx]); + }); return json_waypoints; } diff --git a/include/engine/api/trip_api.hpp b/include/engine/api/trip_api.hpp index 3cd0744fc61..c7086bc3699 100644 --- a/include/engine/api/trip_api.hpp +++ b/include/engine/api/trip_api.hpp @@ -36,10 +36,10 @@ class TripAPI final : public RouteAPI BOOST_ASSERT(sub_trips.size() == sub_routes.size()); 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); + 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)); } response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); @@ -90,8 +90,7 @@ class TripAPI final : public RouteAPI auto trip_index = input_idx_to_trip_idx[input_index]; BOOST_ASSERT(!trip_index.NotUsed()); - auto waypoint = - BaseAPI::MakeWaypoint(parameters.coordinates[input_index], phantoms[input_index]); + 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)); diff --git a/include/engine/geospatial_query.hpp b/include/engine/geospatial_query.hpp index 7b6c015fd06..0c9de69c960 100644 --- a/include/engine/geospatial_query.hpp +++ b/include/engine/geospatial_query.hpp @@ -244,8 +244,8 @@ template class GeospatialQuery bool has_big_component = false; auto results = rtree.Nearest( input_coordinate, - [this, bearing, bearing_range, &has_big_component, - &has_small_component](const EdgeData &data) + [this, bearing, bearing_range, &has_big_component, &has_small_component]( + const EdgeData &data) { auto use_segment = (!has_small_component || (!has_big_component && !data.component.is_tiny)); @@ -290,8 +290,8 @@ template class GeospatialQuery bool has_big_component = false; auto results = rtree.Nearest( input_coordinate, - [this, bearing, bearing_range, &has_big_component, - &has_small_component](const EdgeData &data) + [this, bearing, bearing_range, &has_big_component, &has_small_component]( + const EdgeData &data) { auto use_segment = (!has_small_component || (!has_big_component && !data.component.is_tiny)); @@ -393,10 +393,14 @@ template class GeospatialQuery reverse_weight *= 1.0 - ratio; } - auto transformed = - PhantomNodeWithDistance{PhantomNode{data, forward_weight, forward_offset, - reverse_weight, reverse_offset, point_on_segment}, - current_perpendicular_distance}; + auto transformed = PhantomNodeWithDistance{PhantomNode{data, + forward_weight, + forward_offset, + reverse_weight, + reverse_offset, + point_on_segment, + input_coordinate}, + current_perpendicular_distance}; return transformed; } diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index 488c4a3e6aa..9a7b0e5fa8d 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -40,6 +40,7 @@ std::vector assembleSteps(const DataFacadeT &facade, const bool source_traversed_in_reverse, const bool target_traversed_in_reverse) { + const double constexpr ZERO_DURACTION = 0., ZERO_DISTANCE = 0., NO_BEARING = 0.; const EdgeWeight source_duration = source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight; const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode @@ -56,10 +57,19 @@ std::vector assembleSteps(const DataFacadeT &facade, steps.reserve(number_of_segments); std::size_t segment_index = 0; + BOOST_ASSERT(leg_geometry.locations.size() >= 2); + + // We report the relative position of source/target to the road only within a range that is + // sufficiently different but not full of the path + const constexpr double MINIMAL_RELATIVE_DISTANCE = 5., MAXIMAL_RELATIVE_DISTANCE = 300.; + const auto distance_to_start = util::coordinate_calculation::haversineDistance( + source_node.input_location, leg_geometry.locations[0]); const auto initial_modifier = - leg_geometry.locations.size() >= 3 + distance_to_start >= MINIMAL_RELATIVE_DISTANCE && + distance_to_start <= MAXIMAL_RELATIVE_DISTANCE ? angleToDirectionModifier(util::coordinate_calculation::computeAngle( - leg_geometry.locations[0], leg_geometry.locations[1], leg_geometry.locations[2])) + source_node.input_location, leg_geometry.locations[0], + leg_geometry.locations[1])) : extractor::guidance::DirectionModifier::UTurn; if (leg_data.size() > 0) @@ -84,8 +94,12 @@ std::vector assembleSteps(const DataFacadeT &facade, BOOST_ASSERT(segment_duration >= 0); const auto name = facade.get_name_for_id(path_point.name_id); const auto distance = leg_geometry.segment_distances[segment_index]; - steps.push_back(RouteStep{path_point.name_id, name, segment_duration / 10.0, - distance, path_point.travel_mode, maneuver, + steps.push_back(RouteStep{path_point.name_id, + name, + segment_duration / 10.0, + distance, + path_point.travel_mode, + maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction, @@ -98,8 +112,12 @@ std::vector assembleSteps(const DataFacadeT &facade, const auto distance = leg_geometry.segment_distances[segment_index]; const int duration = segment_duration + target_duration; BOOST_ASSERT(duration >= 0); - steps.push_back(RouteStep{target_node.name_id, facade.get_name_for_id(target_node.name_id), - duration / 10., distance, target_mode, maneuver, + steps.push_back(RouteStep{target_node.name_id, + facade.get_name_for_id(target_node.name_id), + duration / 10., + distance, + target_mode, + maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1}); } @@ -112,35 +130,53 @@ std::vector assembleSteps(const DataFacadeT &facade, // |---| source_duration // |---------| target_duration - StepManeuver maneuver = {source_node.location, 0., 0., + StepManeuver maneuver = {source_node.location, + NO_BEARING, + NO_BEARING, extractor::guidance::TurnInstruction{ extractor::guidance::TurnType::NoTurn, initial_modifier}, - WaypointType::Depart, INVALID_EXIT_NR}; + WaypointType::Depart, + INVALID_EXIT_NR}; int duration = target_duration - source_duration; BOOST_ASSERT(duration >= 0); - steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id), - duration / 10., leg_geometry.segment_distances[segment_index], source_mode, - std::move(maneuver), leg_geometry.FrontIndex(segment_index), + steps.push_back(RouteStep{source_node.name_id, + facade.get_name_for_id(source_node.name_id), + duration / 10., + 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 distance_from_end = util::coordinate_calculation::haversineDistance( + target_node.input_location, leg_geometry.locations.back()); const auto final_modifier = - leg_geometry.locations.size() >= 3 + distance_from_end >= MINIMAL_RELATIVE_DISTANCE && + distance_from_end <= MAXIMAL_RELATIVE_DISTANCE ? angleToDirectionModifier(util::coordinate_calculation::computeAngle( - leg_geometry.locations[leg_geometry.locations.size() - 3], leg_geometry.locations[leg_geometry.locations.size() - 2], - leg_geometry.locations[leg_geometry.locations.size() - 1])) + leg_geometry.locations[leg_geometry.locations.size() - 1], + target_node.input_location)) : extractor::guidance::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., - extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn, - final_modifier}, - WaypointType::Arrive, INVALID_EXIT_NR}, - leg_geometry.locations.size(), leg_geometry.locations.size()}); + steps.push_back( + RouteStep{target_node.name_id, + facade.get_name_for_id(target_node.name_id), + ZERO_DURACTION, + ZERO_DISTANCE, + target_mode, + StepManeuver{target_node.location, + NO_BEARING, + NO_BEARING, + extractor::guidance::TurnInstruction{ + extractor::guidance::TurnType::NoTurn, final_modifier}, + WaypointType::Arrive, + INVALID_EXIT_NR}, + leg_geometry.locations.size(), + leg_geometry.locations.size()}); return steps; } diff --git a/include/engine/hint.hpp b/include/engine/hint.hpp index 4a8d958b189..9409ba3612b 100644 --- a/include/engine/hint.hpp +++ b/include/engine/hint.hpp @@ -43,16 +43,13 @@ namespace engine // Is returned as a temporary identifier for snapped coodinates struct Hint { - util::Coordinate input_coordinate; PhantomNode phantom; std::uint32_t data_checksum; template bool IsValid(const util::Coordinate new_input_coordinates, DataFacadeT &facade) const { - auto is_same_input_coordinate = new_input_coordinates.lon == input_coordinate.lon && - new_input_coordinates.lat == input_coordinate.lat; - return is_same_input_coordinate && phantom.IsValid(facade.GetNumberOfNodes()) && + return phantom.IsValid(facade.GetNumberOfNodes(), new_input_coordinates) && facade.GetCheckSum() == data_checksum; } diff --git a/include/engine/phantom_node.hpp b/include/engine/phantom_node.hpp index e7edbd6142c..6d5ab409eaa 100644 --- a/include/engine/phantom_node.hpp +++ b/include/engine/phantom_node.hpp @@ -56,6 +56,7 @@ struct PhantomNode bool is_tiny_component, unsigned component_id, util::Coordinate location, + util::Coordinate input_location, unsigned short fwd_segment_position, extractor::TravelMode forward_travel_mode, extractor::TravelMode backward_travel_mode) @@ -65,8 +66,8 @@ struct PhantomNode forward_packed_geometry_id(forward_packed_geometry_id_), reverse_packed_geometry_id(reverse_packed_geometry_id_), component{component_id, is_tiny_component}, location(std::move(location)), - fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode), - backward_travel_mode(backward_travel_mode) + input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position), + forward_travel_mode(forward_travel_mode), backward_travel_mode(backward_travel_mode) { } @@ -115,6 +116,11 @@ struct PhantomNode (component.id != INVALID_COMPONENTID) && (name_id != INVALID_NAMEID); } + bool IsValid(const unsigned number_of_nodes, const util::Coordinate queried_coordinate) const + { + return queried_coordinate == input_location && IsValid(number_of_nodes); + } + bool IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); } bool operator==(const PhantomNode &other) const { return location == other.location; } @@ -125,7 +131,8 @@ struct PhantomNode int forward_offset_, int reverse_weight_, int reverse_offset_, - const util::Coordinate foot_point) + const util::Coordinate location_, + const util::Coordinate input_location_) { forward_node_id = other.forward_edge_based_node_id; reverse_node_id = other.reverse_edge_based_node_id; @@ -143,7 +150,8 @@ struct PhantomNode component.id = other.component.id; component.is_tiny = other.component.is_tiny; - location = foot_point; + location = location_; + input_location = input_location_; fwd_segment_position = other.fwd_segment_position; forward_travel_mode = other.forward_travel_mode; @@ -169,6 +177,7 @@ struct PhantomNode static_assert(sizeof(ComponentType) == 4, "ComponentType needs to 4 bytes big"); #endif util::Coordinate location; + util::Coordinate input_location; unsigned short fwd_segment_position; // note 4 bits would suffice for each, // but the saved byte would be padding anyway @@ -177,7 +186,7 @@ struct PhantomNode }; #ifndef _MSC_VER -static_assert(sizeof(PhantomNode) == 52, "PhantomNode has more padding then expected"); +static_assert(sizeof(PhantomNode) == 60, "PhantomNode has more padding then expected"); #endif using PhantomNodePair = std::pair;