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 <boost/assert.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <vector>
@ -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)
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;
}
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;

View File

@ -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));

View File

@ -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;
});

View File

@ -17,6 +17,8 @@
#include "util/integer_range.hpp"
#include <boost/range/algorithm/transform.hpp>
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)
boost::range::transform(phantoms, std::back_inserter(json_waypoints.values),
[this](const PhantomNode &phantom)
{
json_waypoints.values.push_back(BaseAPI::MakeWaypoint(*coordinate_iter, *phantom_iter));
}
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::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(
BaseAPI::MakeWaypoint(parameters.coordinates[idx], phantoms[idx]));
}
BOOST_ASSERT(idx < phantoms.size());
return BaseAPI::MakeWaypoint(phantoms[idx]);
});
return json_waypoints;
}

View File

@ -36,8 +36,8 @@ class TripAPI final : public RouteAPI
BOOST_ASSERT(sub_trips.size() == sub_routes.size());
for (auto index : util::irange<std::size_t>(0UL, sub_trips.size()))
{
auto route = MakeRoute(
sub_routes[index].segment_end_coordinates, sub_routes[index].unpacked_path_segments,
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));
@ -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));

View File

@ -244,8 +244,8 @@ template <typename RTreeT, typename DataFacadeT> 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 <typename RTreeT, typename DataFacadeT> 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,9 +393,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
reverse_weight *= 1.0 - ratio;
}
auto transformed =
PhantomNodeWithDistance{PhantomNode{data, forward_weight, forward_offset,
reverse_weight, reverse_offset, point_on_segment},
auto transformed = PhantomNodeWithDistance{PhantomNode{data,
forward_weight,
forward_offset,
reverse_weight,
reverse_offset,
point_on_segment,
input_coordinate},
current_perpendicular_distance};
return transformed;

View File

@ -40,6 +40,7 @@ std::vector<RouteStep> 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<RouteStep> 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<RouteStep> 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<RouteStep> 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<RouteStep> 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;
}

View File

@ -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 <typename DataFacadeT>
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;
}

View File

@ -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<PhantomNode, PhantomNode>;