implements relative position feature based on coordinates

This commit is contained in:
Moritz Kobitzsch 2016-03-08 16:46:01 +01:00 committed by Patrick Niklaus
parent 873950ee86
commit fbdafca4f2
9 changed files with 114 additions and 70 deletions

View File

@ -8,6 +8,7 @@
#include "engine/hint.hpp" #include "engine/hint.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <vector> #include <vector>
@ -33,24 +34,22 @@ class BaseAPI
util::json::Array waypoints; util::json::Array waypoints;
waypoints.values.resize(parameters.coordinates.size()); waypoints.values.resize(parameters.coordinates.size());
waypoints.values[0] = MakeWaypoint(parameters.coordinates.front(), waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom);
segment_end_coordinates.front().source_phantom);
auto coord_iter = std::next(parameters.coordinates.begin());
auto out_iter = std::next(waypoints.values.begin()); auto out_iter = std::next(waypoints.values.begin());
for (const auto &phantoms : segment_end_coordinates) boost::range::transform(segment_end_coordinates, out_iter,
{ [this](const PhantomNodes &phantom_pair)
*out_iter++ = MakeWaypoint(*coord_iter++, phantoms.target_phantom); {
} return MakeWaypoint(phantom_pair.target_phantom);
});
return waypoints; return waypoints;
} }
protected: protected:
util::json::Object MakeWaypoint(const util::Coordinate input_coordinate, util::json::Object MakeWaypoint(const PhantomNode &phantom) const
const PhantomNode &phantom) const
{ {
return json::makeWaypoint(phantom.location, facade.get_name_for_id(phantom.name_id), 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; const datafacade::BaseDataFacade &facade;

View File

@ -98,7 +98,7 @@ class MatchAPI final : public RouteAPI
} }
const auto &phantom = const auto &phantom =
sub_matchings[matching_index.sub_matching_index].nodes[matching_index.point_index]; 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["matchings_index"] = matching_index.sub_matching_index;
waypoint.values["waypoint_index"] = matching_index.point_index; waypoint.values["waypoint_index"] = matching_index.point_index;
waypoints.values.push_back(std::move(waypoint)); waypoints.values.push_back(std::move(waypoint));

View File

@ -38,8 +38,7 @@ class NearestAPI final : public BaseAPI
waypoints.values.begin(), waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance) [this](const PhantomNodeWithDistance &phantom_with_distance)
{ {
auto waypoint = MakeWaypoint(parameters.coordinates.front(), auto waypoint = MakeWaypoint(phantom_with_distance.phantom_node);
phantom_with_distance.phantom_node);
waypoint.values["distance"] = phantom_with_distance.distance; waypoint.values["distance"] = phantom_with_distance.distance;
return waypoint; return waypoint;
}); });

View File

@ -17,6 +17,8 @@
#include "util/integer_range.hpp" #include "util/integer_range.hpp"
#include <boost/range/algorithm/transform.hpp>
namespace osrm namespace osrm
{ {
namespace engine namespace engine
@ -72,13 +74,12 @@ class TableAPI final : public BaseAPI
util::json::Array json_waypoints; util::json::Array json_waypoints;
json_waypoints.values.reserve(phantoms.size()); json_waypoints.values.reserve(phantoms.size());
BOOST_ASSERT(phantoms.size() == parameters.coordinates.size()); BOOST_ASSERT(phantoms.size() == parameters.coordinates.size());
auto phantom_iter = phantoms.begin();
auto coordinate_iter = parameters.coordinates.begin(); boost::range::transform(phantoms, std::back_inserter(json_waypoints.values),
for (; phantom_iter != phantoms.end() && coordinate_iter != parameters.coordinates.end(); [this](const PhantomNode &phantom)
++phantom_iter, ++coordinate_iter) {
{ return BaseAPI::MakeWaypoint(phantom);
json_waypoints.values.push_back(BaseAPI::MakeWaypoint(*coordinate_iter, *phantom_iter)); });
}
return json_waypoints; return json_waypoints;
} }
@ -87,12 +88,12 @@ class TableAPI final : public BaseAPI
{ {
util::json::Array json_waypoints; util::json::Array json_waypoints;
json_waypoints.values.reserve(indices.size()); json_waypoints.values.reserve(indices.size());
for (auto idx : indices) boost::range::transform(indices, std::back_inserter(json_waypoints.values),
{ [this, phantoms](const std::size_t idx)
BOOST_ASSERT(idx < phantoms.size() && idx < parameters.coordinates.size()); {
json_waypoints.values.push_back( BOOST_ASSERT(idx < phantoms.size());
BaseAPI::MakeWaypoint(parameters.coordinates[idx], phantoms[idx])); return BaseAPI::MakeWaypoint(phantoms[idx]);
} });
return json_waypoints; return json_waypoints;
} }

View File

@ -36,10 +36,10 @@ class TripAPI final : public RouteAPI
BOOST_ASSERT(sub_trips.size() == sub_routes.size()); BOOST_ASSERT(sub_trips.size() == sub_routes.size());
for (auto index : util::irange<std::size_t>(0UL, sub_trips.size())) for (auto index : util::irange<std::size_t>(0UL, sub_trips.size()))
{ {
auto route = MakeRoute( auto route = MakeRoute(sub_routes[index].segment_end_coordinates,
sub_routes[index].segment_end_coordinates, sub_routes[index].unpacked_path_segments, sub_routes[index].unpacked_path_segments,
sub_routes[index].source_traversed_in_reverse, sub_routes[index].source_traversed_in_reverse,
sub_routes[index].target_traversed_in_reverse); sub_routes[index].target_traversed_in_reverse);
routes.values.push_back(std::move(route)); routes.values.push_back(std::move(route));
} }
response.values["waypoints"] = MakeWaypoints(sub_trips, phantoms); 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]; auto trip_index = input_idx_to_trip_idx[input_index];
BOOST_ASSERT(!trip_index.NotUsed()); BOOST_ASSERT(!trip_index.NotUsed());
auto waypoint = auto waypoint = BaseAPI::MakeWaypoint(phantoms[input_index]);
BaseAPI::MakeWaypoint(parameters.coordinates[input_index], phantoms[input_index]);
waypoint.values["trips_index"] = trip_index.sub_trip_index; waypoint.values["trips_index"] = trip_index.sub_trip_index;
waypoint.values["waypoint_index"] = trip_index.point_index; waypoint.values["waypoint_index"] = trip_index.point_index;
waypoints.values.push_back(std::move(waypoint)); waypoints.values.push_back(std::move(waypoint));

View File

@ -244,8 +244,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool has_big_component = false; bool has_big_component = false;
auto results = rtree.Nearest( auto results = rtree.Nearest(
input_coordinate, input_coordinate,
[this, bearing, bearing_range, &has_big_component, [this, bearing, bearing_range, &has_big_component, &has_small_component](
&has_small_component](const EdgeData &data) const EdgeData &data)
{ {
auto use_segment = auto use_segment =
(!has_small_component || (!has_big_component && !data.component.is_tiny)); (!has_small_component || (!has_big_component && !data.component.is_tiny));
@ -290,8 +290,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
bool has_big_component = false; bool has_big_component = false;
auto results = rtree.Nearest( auto results = rtree.Nearest(
input_coordinate, input_coordinate,
[this, bearing, bearing_range, &has_big_component, [this, bearing, bearing_range, &has_big_component, &has_small_component](
&has_small_component](const EdgeData &data) const EdgeData &data)
{ {
auto use_segment = auto use_segment =
(!has_small_component || (!has_big_component && !data.component.is_tiny)); (!has_small_component || (!has_big_component && !data.component.is_tiny));
@ -393,10 +393,14 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_weight *= 1.0 - ratio; reverse_weight *= 1.0 - ratio;
} }
auto transformed = auto transformed = PhantomNodeWithDistance{PhantomNode{data,
PhantomNodeWithDistance{PhantomNode{data, forward_weight, forward_offset, forward_weight,
reverse_weight, reverse_offset, point_on_segment}, forward_offset,
current_perpendicular_distance}; reverse_weight,
reverse_offset,
point_on_segment,
input_coordinate},
current_perpendicular_distance};
return transformed; return transformed;
} }

View File

@ -40,6 +40,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const bool source_traversed_in_reverse, const bool source_traversed_in_reverse,
const bool target_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 = const EdgeWeight source_duration =
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight; 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 const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
@ -56,10 +57,19 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
steps.reserve(number_of_segments); steps.reserve(number_of_segments);
std::size_t segment_index = 0; 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 = 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( ? 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; : extractor::guidance::DirectionModifier::UTurn;
if (leg_data.size() > 0) if (leg_data.size() > 0)
@ -84,8 +94,12 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
BOOST_ASSERT(segment_duration >= 0); BOOST_ASSERT(segment_duration >= 0);
const auto name = facade.get_name_for_id(path_point.name_id); const auto name = facade.get_name_for_id(path_point.name_id);
const auto distance = leg_geometry.segment_distances[segment_index]; const auto distance = leg_geometry.segment_distances[segment_index];
steps.push_back(RouteStep{path_point.name_id, name, segment_duration / 10.0, steps.push_back(RouteStep{path_point.name_id,
distance, path_point.travel_mode, maneuver, name,
segment_duration / 10.0,
distance,
path_point.travel_mode,
maneuver,
leg_geometry.FrontIndex(segment_index), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1}); leg_geometry.BackIndex(segment_index) + 1});
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction, maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
@ -98,8 +112,12 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const auto distance = leg_geometry.segment_distances[segment_index]; const auto distance = leg_geometry.segment_distances[segment_index];
const int duration = segment_duration + target_duration; const int duration = segment_duration + target_duration;
BOOST_ASSERT(duration >= 0); BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{target_node.name_id, facade.get_name_for_id(target_node.name_id), steps.push_back(RouteStep{target_node.name_id,
duration / 10., distance, target_mode, maneuver, facade.get_name_for_id(target_node.name_id),
duration / 10.,
distance,
target_mode,
maneuver,
leg_geometry.FrontIndex(segment_index), leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1}); leg_geometry.BackIndex(segment_index) + 1});
} }
@ -112,35 +130,53 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
// |---| source_duration // |---| source_duration
// |---------| target_duration // |---------| target_duration
StepManeuver maneuver = {source_node.location, 0., 0., StepManeuver maneuver = {source_node.location,
NO_BEARING,
NO_BEARING,
extractor::guidance::TurnInstruction{ extractor::guidance::TurnInstruction{
extractor::guidance::TurnType::NoTurn, initial_modifier}, extractor::guidance::TurnType::NoTurn, initial_modifier},
WaypointType::Depart, INVALID_EXIT_NR}; WaypointType::Depart,
INVALID_EXIT_NR};
int duration = target_duration - source_duration; int duration = target_duration - source_duration;
BOOST_ASSERT(duration >= 0); BOOST_ASSERT(duration >= 0);
steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id), steps.push_back(RouteStep{source_node.name_id,
duration / 10., leg_geometry.segment_distances[segment_index], source_mode, facade.get_name_for_id(source_node.name_id),
std::move(maneuver), leg_geometry.FrontIndex(segment_index), duration / 10.,
leg_geometry.segment_distances[segment_index],
source_mode,
std::move(maneuver),
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1}); leg_geometry.BackIndex(segment_index) + 1});
} }
BOOST_ASSERT(segment_index == number_of_segments - 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 = 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( ? 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() - 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; : extractor::guidance::DirectionModifier::UTurn;
// This step has length zero, the only reason we need it is the target location // This step has length zero, the only reason we need it is the target location
steps.push_back(RouteStep{ steps.push_back(
target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode, RouteStep{target_node.name_id,
StepManeuver{target_node.location, 0., 0., facade.get_name_for_id(target_node.name_id),
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn, ZERO_DURACTION,
final_modifier}, ZERO_DISTANCE,
WaypointType::Arrive, INVALID_EXIT_NR}, target_mode,
leg_geometry.locations.size(), leg_geometry.locations.size()}); 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; return steps;
} }

View File

@ -43,16 +43,13 @@ namespace engine
// Is returned as a temporary identifier for snapped coodinates // Is returned as a temporary identifier for snapped coodinates
struct Hint struct Hint
{ {
util::Coordinate input_coordinate;
PhantomNode phantom; PhantomNode phantom;
std::uint32_t data_checksum; std::uint32_t data_checksum;
template <typename DataFacadeT> template <typename DataFacadeT>
bool IsValid(const util::Coordinate new_input_coordinates, DataFacadeT &facade) const bool IsValid(const util::Coordinate new_input_coordinates, DataFacadeT &facade) const
{ {
auto is_same_input_coordinate = new_input_coordinates.lon == input_coordinate.lon && return phantom.IsValid(facade.GetNumberOfNodes(), new_input_coordinates) &&
new_input_coordinates.lat == input_coordinate.lat;
return is_same_input_coordinate && phantom.IsValid(facade.GetNumberOfNodes()) &&
facade.GetCheckSum() == data_checksum; facade.GetCheckSum() == data_checksum;
} }

View File

@ -56,6 +56,7 @@ struct PhantomNode
bool is_tiny_component, bool is_tiny_component,
unsigned component_id, unsigned component_id,
util::Coordinate location, util::Coordinate location,
util::Coordinate input_location,
unsigned short fwd_segment_position, unsigned short fwd_segment_position,
extractor::TravelMode forward_travel_mode, extractor::TravelMode forward_travel_mode,
extractor::TravelMode backward_travel_mode) extractor::TravelMode backward_travel_mode)
@ -65,8 +66,8 @@ struct PhantomNode
forward_packed_geometry_id(forward_packed_geometry_id_), forward_packed_geometry_id(forward_packed_geometry_id_),
reverse_packed_geometry_id(reverse_packed_geometry_id_), reverse_packed_geometry_id(reverse_packed_geometry_id_),
component{component_id, is_tiny_component}, location(std::move(location)), component{component_id, is_tiny_component}, location(std::move(location)),
fwd_segment_position(fwd_segment_position), forward_travel_mode(forward_travel_mode), input_location(std::move(input_location)), fwd_segment_position(fwd_segment_position),
backward_travel_mode(backward_travel_mode) 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); (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 IsValid() const { return location.IsValid() && (name_id != INVALID_NAMEID); }
bool operator==(const PhantomNode &other) const { return location == other.location; } bool operator==(const PhantomNode &other) const { return location == other.location; }
@ -125,7 +131,8 @@ struct PhantomNode
int forward_offset_, int forward_offset_,
int reverse_weight_, int reverse_weight_,
int reverse_offset_, 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; forward_node_id = other.forward_edge_based_node_id;
reverse_node_id = other.reverse_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.id = other.component.id;
component.is_tiny = other.component.is_tiny; component.is_tiny = other.component.is_tiny;
location = foot_point; location = location_;
input_location = input_location_;
fwd_segment_position = other.fwd_segment_position; fwd_segment_position = other.fwd_segment_position;
forward_travel_mode = other.forward_travel_mode; forward_travel_mode = other.forward_travel_mode;
@ -169,6 +177,7 @@ struct PhantomNode
static_assert(sizeof(ComponentType) == 4, "ComponentType needs to 4 bytes big"); static_assert(sizeof(ComponentType) == 4, "ComponentType needs to 4 bytes big");
#endif #endif
util::Coordinate location; util::Coordinate location;
util::Coordinate input_location;
unsigned short fwd_segment_position; unsigned short fwd_segment_position;
// note 4 bits would suffice for each, // note 4 bits would suffice for each,
// but the saved byte would be padding anyway // but the saved byte would be padding anyway
@ -177,7 +186,7 @@ struct PhantomNode
}; };
#ifndef _MSC_VER #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 #endif
using PhantomNodePair = std::pair<PhantomNode, PhantomNode>; using PhantomNodePair = std::pair<PhantomNode, PhantomNode>;