Upgrade clang-format to version 15 (#6859)
This commit is contained in:
@@ -129,7 +129,8 @@ util::json::Object makeIntersection(const guidance::IntermediateIntersection &in
|
||||
std::transform(intersection.entry.begin(),
|
||||
intersection.entry.end(),
|
||||
std::back_inserter(entry.values),
|
||||
[](const bool has_entry) -> util::json::Value {
|
||||
[](const bool has_entry) -> util::json::Value
|
||||
{
|
||||
if (has_entry)
|
||||
return util::json::True();
|
||||
else
|
||||
@@ -151,11 +152,11 @@ util::json::Object makeIntersection(const guidance::IntermediateIntersection &in
|
||||
{
|
||||
util::json::Array classes;
|
||||
classes.values.reserve(intersection.classes.size());
|
||||
std::transform(
|
||||
intersection.classes.begin(),
|
||||
intersection.classes.end(),
|
||||
std::back_inserter(classes.values),
|
||||
[](const std::string &class_name) { return util::json::String{class_name}; });
|
||||
std::transform(intersection.classes.begin(),
|
||||
intersection.classes.end(),
|
||||
std::back_inserter(classes.values),
|
||||
[](const std::string &class_name)
|
||||
{ return util::json::String{class_name}; });
|
||||
result.values["classes"] = std::move(classes);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,11 @@ std::vector<util::Coordinate> douglasPeucker(std::vector<util::Coordinate>::cons
|
||||
}
|
||||
|
||||
std::vector<util::FloatCoordinate> projected_coordinates(size);
|
||||
std::transform(begin, end, projected_coordinates.begin(), [](const util::Coordinate coord) {
|
||||
return util::web_mercator::fromWGS84(coord);
|
||||
});
|
||||
std::transform(begin,
|
||||
end,
|
||||
projected_coordinates.begin(),
|
||||
[](const util::Coordinate coord)
|
||||
{ return util::web_mercator::fromWGS84(coord); });
|
||||
|
||||
std::vector<bool> is_necessary(size, false);
|
||||
BOOST_ASSERT(is_necessary.size() >= 2);
|
||||
|
||||
@@ -9,9 +9,8 @@ bool EngineConfig::IsValid() const
|
||||
// leads to an empty path
|
||||
const bool all_path_are_empty = storage_config.GetPath("").empty();
|
||||
|
||||
const auto unlimited_or_more_than = [](const auto v, const auto limit) {
|
||||
return v == -1 || v > limit;
|
||||
};
|
||||
const auto unlimited_or_more_than = [](const auto v, const auto limit)
|
||||
{ return v == -1 || v > limit; };
|
||||
|
||||
const bool limits_valid =
|
||||
unlimited_or_more_than(max_locations_distance_table, 2) &&
|
||||
|
||||
@@ -40,22 +40,21 @@ unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometri
|
||||
std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &leg_geometries,
|
||||
const bool use_simplification)
|
||||
{
|
||||
auto overview_size =
|
||||
std::accumulate(leg_geometries.begin(),
|
||||
leg_geometries.end(),
|
||||
0,
|
||||
[](const std::size_t sum, const LegGeometry &leg_geometry) {
|
||||
return sum + leg_geometry.locations.size();
|
||||
}) -
|
||||
leg_geometries.size() + 1;
|
||||
auto overview_size = std::accumulate(leg_geometries.begin(),
|
||||
leg_geometries.end(),
|
||||
0,
|
||||
[](const std::size_t sum, const LegGeometry &leg_geometry)
|
||||
{ return sum + leg_geometry.locations.size(); }) -
|
||||
leg_geometries.size() + 1;
|
||||
std::vector<util::Coordinate> overview_geometry;
|
||||
overview_geometry.reserve(overview_size);
|
||||
|
||||
using GeometryIter = decltype(overview_geometry)::const_iterator;
|
||||
|
||||
auto leg_reverse_index = leg_geometries.size();
|
||||
const auto insert_without_overlap = [&leg_reverse_index, &overview_geometry](GeometryIter begin,
|
||||
GeometryIter end) {
|
||||
const auto insert_without_overlap =
|
||||
[&leg_reverse_index, &overview_geometry](GeometryIter begin, GeometryIter end)
|
||||
{
|
||||
// not the last leg
|
||||
if (leg_reverse_index > 1)
|
||||
{
|
||||
|
||||
@@ -7,18 +7,21 @@ namespace osrm::engine::guidance
|
||||
|
||||
Route assembleRoute(const std::vector<RouteLeg> &route_legs)
|
||||
{
|
||||
auto distance = std::accumulate(
|
||||
route_legs.begin(), route_legs.end(), 0., [](const double sum, const RouteLeg &leg) {
|
||||
return sum + leg.distance;
|
||||
});
|
||||
auto duration = std::accumulate(
|
||||
route_legs.begin(), route_legs.end(), 0., [](const double sum, const RouteLeg &leg) {
|
||||
return sum + leg.duration;
|
||||
});
|
||||
auto weight = std::accumulate(
|
||||
route_legs.begin(), route_legs.end(), 0., [](const double sum, const RouteLeg &leg) {
|
||||
return sum + leg.weight;
|
||||
});
|
||||
auto distance =
|
||||
std::accumulate(route_legs.begin(),
|
||||
route_legs.end(),
|
||||
0.,
|
||||
[](const double sum, const RouteLeg &leg) { return sum + leg.distance; });
|
||||
auto duration =
|
||||
std::accumulate(route_legs.begin(),
|
||||
route_legs.end(),
|
||||
0.,
|
||||
[](const double sum, const RouteLeg &leg) { return sum + leg.duration; });
|
||||
auto weight =
|
||||
std::accumulate(route_legs.begin(),
|
||||
route_legs.end(),
|
||||
0.,
|
||||
[](const double sum, const RouteLeg &leg) { return sum + leg.weight; });
|
||||
|
||||
return Route{distance, duration, weight};
|
||||
}
|
||||
|
||||
@@ -102,7 +102,8 @@ bool isStaggeredIntersection(const RouteStepIterator step_prior_to_intersection,
|
||||
// If adjusted, make sure to check validity of the is_right/is_left classification below
|
||||
const constexpr auto MAX_STAGGERED_DISTANCE = 3; // debatable, but keep short to be on safe side
|
||||
|
||||
const auto angle = [](const RouteStep &step) {
|
||||
const auto angle = [](const RouteStep &step)
|
||||
{
|
||||
const auto &intersection = step.intersections.front();
|
||||
const auto entry_bearing = util::bearing::reverse(intersection.bearings[intersection.in]);
|
||||
const auto exit_bearing = intersection.bearings[intersection.out];
|
||||
|
||||
@@ -59,7 +59,8 @@ double findTotalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_ste
|
||||
// c
|
||||
// |
|
||||
// d
|
||||
const auto use_total_angle = [&]() {
|
||||
const auto use_total_angle = [&]()
|
||||
{
|
||||
// only consider actual turns in combination:
|
||||
if (angularDeviation(total_angle, 180) < 0.5 * NARROW_TURN_ANGLE)
|
||||
return false;
|
||||
@@ -99,7 +100,8 @@ inline void handleSliproad(RouteStepIterator sliproad_step)
|
||||
{
|
||||
// find the next step after the sliproad step itself (this is not necessarily the next step,
|
||||
// since we might have to skip over traffic lights/node penalties)
|
||||
auto next_step = [&sliproad_step]() {
|
||||
auto next_step = [&sliproad_step]()
|
||||
{
|
||||
auto next_step = findNextTurn(sliproad_step);
|
||||
while (isTrafficLightStep(*next_step))
|
||||
{
|
||||
@@ -196,7 +198,8 @@ void AdjustToCombinedTurnStrategy::operator()(RouteStep &step_at_turn_location,
|
||||
: getTurnDirection(angle);
|
||||
|
||||
// a turn that is a new name or straight (turn/continue)
|
||||
const auto is_non_turn = [](const RouteStep &step) {
|
||||
const auto is_non_turn = [](const RouteStep &step)
|
||||
{
|
||||
return hasTurnType(step, TurnType::NewName) ||
|
||||
(hasTurnType(step, TurnType::Turn) &&
|
||||
hasModifier(step, DirectionModifier::Straight)) ||
|
||||
@@ -307,7 +310,8 @@ void SegregatedTurnStrategy::operator()(RouteStep &step_at_turn_location,
|
||||
// Used to control updating of the modifier based on turn direction
|
||||
bool update_modifier_for_turn_direction = true;
|
||||
|
||||
const auto calculate_turn_angle = [](const RouteStep &entry_step, const RouteStep &exit_step) {
|
||||
const auto calculate_turn_angle = [](const RouteStep &entry_step, const RouteStep &exit_step)
|
||||
{
|
||||
return util::bearing::angleBetween(entry_step.maneuver.bearing_before,
|
||||
exit_step.maneuver.bearing_after);
|
||||
};
|
||||
@@ -316,7 +320,8 @@ void SegregatedTurnStrategy::operator()(RouteStep &step_at_turn_location,
|
||||
const auto turn_angle = calculate_turn_angle(step_at_turn_location, transfer_from_step);
|
||||
const auto turn_direction = getTurnDirection(turn_angle);
|
||||
|
||||
const auto is_straight_step = [](const RouteStep &step) {
|
||||
const auto is_straight_step = [](const RouteStep &step)
|
||||
{
|
||||
return ((hasTurnType(step, TurnType::NewName) || hasTurnType(step, TurnType::Continue) ||
|
||||
hasTurnType(step, TurnType::Suppressed) || hasTurnType(step, TurnType::Turn)) &&
|
||||
(hasModifier(step, DirectionModifier::Straight) ||
|
||||
@@ -324,7 +329,8 @@ void SegregatedTurnStrategy::operator()(RouteStep &step_at_turn_location,
|
||||
hasModifier(step, DirectionModifier::SlightRight)));
|
||||
};
|
||||
|
||||
const auto is_turn_step = [](const RouteStep &step) {
|
||||
const auto is_turn_step = [](const RouteStep &step)
|
||||
{
|
||||
return (hasTurnType(step, TurnType::Turn) || hasTurnType(step, TurnType::Continue) ||
|
||||
hasTurnType(step, TurnType::NewName) || hasTurnType(step, TurnType::Suppressed));
|
||||
};
|
||||
|
||||
@@ -17,7 +17,8 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
||||
const double min_distance_needed_for_lane_change)
|
||||
{
|
||||
// Lane anticipation works on contiguous ranges of short steps that have lane information
|
||||
const auto is_short_has_lanes = [&](const RouteStep &step) {
|
||||
const auto is_short_has_lanes = [&](const RouteStep &step)
|
||||
{
|
||||
const auto has_lanes = step.intersections.front().lanes.lanes_in_turn > 0;
|
||||
|
||||
if (!has_lanes)
|
||||
@@ -45,7 +46,8 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
||||
|
||||
std::vector<StepIterRange> quick_lanes_ranges;
|
||||
|
||||
const auto range_back_inserter = [&](StepIterRange range) {
|
||||
const auto range_back_inserter = [&](StepIterRange range)
|
||||
{
|
||||
if (std::distance(range.first, range.second) > 1)
|
||||
quick_lanes_ranges.push_back(std::move(range));
|
||||
};
|
||||
@@ -58,7 +60,8 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
||||
|
||||
// Walk backwards over all turns, constraining possible turn lanes.
|
||||
// Later turn lanes constrain earlier ones: we have to anticipate lane changes.
|
||||
const auto constrain_lanes = [&](const StepIterRange &turns) {
|
||||
const auto constrain_lanes = [&](const StepIterRange &turns)
|
||||
{
|
||||
const std::reverse_iterator<StepIter> rev_first{turns.second};
|
||||
const std::reverse_iterator<StepIter> rev_last{turns.first};
|
||||
|
||||
@@ -74,127 +77,135 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
|
||||
// segment for a lane switch, but the total distance shouldn't be unlimited.
|
||||
double distance_to_constrained = 0.0;
|
||||
|
||||
util::for_each_pair(rev_first, rev_last, [&](RouteStep ¤t, RouteStep &previous) {
|
||||
const auto current_inst = current.maneuver.instruction;
|
||||
const auto current_lanes = current.intersections.front().lanes;
|
||||
|
||||
// Constrain the previous turn's lanes
|
||||
auto &previous_lanes = previous.intersections.front().lanes;
|
||||
const auto previous_inst = previous.maneuver.instruction;
|
||||
|
||||
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
|
||||
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
|
||||
// otherwise nothing to constrain
|
||||
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
|
||||
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
|
||||
|
||||
// only prevent use lanes due to making all turns. don't make turns during curvy
|
||||
// segments
|
||||
if (previous_inst.type == TurnType::Suppressed)
|
||||
distance_to_constrained += previous.distance;
|
||||
else
|
||||
distance_to_constrained = 0.;
|
||||
|
||||
const auto lane_delta = previous_lanes.lanes_in_turn - current_lanes.lanes_in_turn;
|
||||
const auto can_make_all_turns =
|
||||
distance_to_constrained > lane_delta * min_distance_needed_for_lane_change;
|
||||
|
||||
if (!lanes_to_constrain || !lanes_fan_in || can_make_all_turns)
|
||||
return;
|
||||
|
||||
// We do not have a mapping from lanes to lanes. All we have is the lanes in the turn
|
||||
// and all the lanes at that situation. To perfectly handle lane anticipation in cases
|
||||
// where lanes in the turn fan in but for example the overall lanes at that location
|
||||
// fan out, we would have to know the asymmetric mapping of lanes. This is currently
|
||||
// not possible at the moment. In the following we implement a heuristic instead.
|
||||
const LaneID current_num_lanes_right_of_turn = current.NumLanesToTheRight();
|
||||
const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft();
|
||||
|
||||
// 0/ Tag keep straight with the next turn's direction if available
|
||||
const auto previous_is_straight =
|
||||
!isLeftTurn(previous_inst) && !isRightTurn(previous_inst);
|
||||
|
||||
if (previous_is_straight)
|
||||
util::for_each_pair(
|
||||
rev_first,
|
||||
rev_last,
|
||||
[&](RouteStep ¤t, RouteStep &previous)
|
||||
{
|
||||
if (isLeftTurn(current_inst) || is_straight_left.count(¤t) > 0)
|
||||
is_straight_left.insert(&previous);
|
||||
else if (isRightTurn(current_inst) || is_straight_right.count(¤t) > 0)
|
||||
is_straight_right.insert(&previous);
|
||||
}
|
||||
const auto current_inst = current.maneuver.instruction;
|
||||
const auto current_lanes = current.intersections.front().lanes;
|
||||
|
||||
// 1/ How to anticipate left, right:
|
||||
const auto anticipate_for_left_turn = [&] {
|
||||
// Current turn is left turn, already keep left during previous turn.
|
||||
// This implies constraining the rightmost lanes in previous step.
|
||||
LaneID new_first_lane_from_the_right =
|
||||
previous_lanes.first_lane_from_the_right // start from rightmost lane
|
||||
+ previous_lanes.lanes_in_turn // one past leftmost lane
|
||||
- current_lanes.lanes_in_turn; // back number of new lanes
|
||||
// Constrain the previous turn's lanes
|
||||
auto &previous_lanes = previous.intersections.front().lanes;
|
||||
const auto previous_inst = previous.maneuver.instruction;
|
||||
|
||||
// The leftmost target lanes might not be involved in the turn. Figure out
|
||||
// how many lanes are to the left and not in the turn.
|
||||
new_first_lane_from_the_right -=
|
||||
std::min(current_num_lanes_left_of_turn, current_lanes.lanes_in_turn);
|
||||
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
|
||||
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
|
||||
// otherwise nothing to constrain
|
||||
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
|
||||
const bool lanes_fan_in =
|
||||
previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
|
||||
|
||||
previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
|
||||
};
|
||||
// only prevent use lanes due to making all turns. don't make turns during curvy
|
||||
// segments
|
||||
if (previous_inst.type == TurnType::Suppressed)
|
||||
distance_to_constrained += previous.distance;
|
||||
else
|
||||
distance_to_constrained = 0.;
|
||||
|
||||
const auto anticipate_for_right_turn = [&] {
|
||||
// Current turn is right turn, already keep right during the previous turn.
|
||||
// This implies constraining the leftmost lanes in the previous turn step.
|
||||
LaneID new_first_lane_from_the_right = previous_lanes.first_lane_from_the_right;
|
||||
const auto lane_delta = previous_lanes.lanes_in_turn - current_lanes.lanes_in_turn;
|
||||
const auto can_make_all_turns =
|
||||
distance_to_constrained > lane_delta * min_distance_needed_for_lane_change;
|
||||
|
||||
// The rightmost target lanes might not be involved in the turn. Figure out
|
||||
// how many lanes are to the right and not in the turn.
|
||||
new_first_lane_from_the_right +=
|
||||
std::min(current_num_lanes_right_of_turn, current_lanes.lanes_in_turn);
|
||||
if (!lanes_to_constrain || !lanes_fan_in || can_make_all_turns)
|
||||
return;
|
||||
|
||||
previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
|
||||
};
|
||||
// We do not have a mapping from lanes to lanes. All we have is the lanes in the
|
||||
// turn and all the lanes at that situation. To perfectly handle lane anticipation
|
||||
// in cases where lanes in the turn fan in but for example the overall lanes at that
|
||||
// location fan out, we would have to know the asymmetric mapping of lanes. This is
|
||||
// currently not possible at the moment. In the following we implement a heuristic
|
||||
// instead.
|
||||
const LaneID current_num_lanes_right_of_turn = current.NumLanesToTheRight();
|
||||
const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft();
|
||||
|
||||
// 2/ When to anticipate a left, right turn
|
||||
if (isLeftTurn(current_inst))
|
||||
anticipate_for_left_turn();
|
||||
else if (isRightTurn(current_inst))
|
||||
anticipate_for_right_turn();
|
||||
else // keepStraight
|
||||
{
|
||||
// Heuristic: we do not have a from-lanes -> to-lanes mapping. What we use
|
||||
// here instead in addition is the number of all lanes (not only the lanes
|
||||
// in a turn):
|
||||
//
|
||||
// -v-v v-v- straight follows
|
||||
// | | | |
|
||||
// <- v v -> keep straight here
|
||||
// | |
|
||||
// <-| |->
|
||||
//
|
||||
// A route from the top left to the bottom right here goes over a keep
|
||||
// straight. If we handle all keep straights as right turns (in right-sided
|
||||
// driving), we wrongly guide the user to the rightmost lanes in the first turn.
|
||||
// Not only is this wrong but the opposite of what we expect.
|
||||
//
|
||||
// The following implements a heuristic to determine a keep straight's
|
||||
// direction in relation to the next step. In the above example we would get:
|
||||
//
|
||||
// coming from right, going to left (in direction of way) -> handle as left turn
|
||||
// 0/ Tag keep straight with the next turn's direction if available
|
||||
const auto previous_is_straight =
|
||||
!isLeftTurn(previous_inst) && !isRightTurn(previous_inst);
|
||||
|
||||
if (is_straight_left.count(¤t) > 0)
|
||||
if (previous_is_straight)
|
||||
{
|
||||
if (isLeftTurn(current_inst) || is_straight_left.count(¤t) > 0)
|
||||
is_straight_left.insert(&previous);
|
||||
else if (isRightTurn(current_inst) || is_straight_right.count(¤t) > 0)
|
||||
is_straight_right.insert(&previous);
|
||||
}
|
||||
|
||||
// 1/ How to anticipate left, right:
|
||||
const auto anticipate_for_left_turn = [&]
|
||||
{
|
||||
// Current turn is left turn, already keep left during previous turn.
|
||||
// This implies constraining the rightmost lanes in previous step.
|
||||
LaneID new_first_lane_from_the_right =
|
||||
previous_lanes.first_lane_from_the_right // start from rightmost lane
|
||||
+ previous_lanes.lanes_in_turn // one past leftmost lane
|
||||
- current_lanes.lanes_in_turn; // back number of new lanes
|
||||
|
||||
// The leftmost target lanes might not be involved in the turn. Figure out
|
||||
// how many lanes are to the left and not in the turn.
|
||||
new_first_lane_from_the_right -=
|
||||
std::min(current_num_lanes_left_of_turn, current_lanes.lanes_in_turn);
|
||||
|
||||
previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
|
||||
};
|
||||
|
||||
const auto anticipate_for_right_turn = [&]
|
||||
{
|
||||
// Current turn is right turn, already keep right during the previous turn.
|
||||
// This implies constraining the leftmost lanes in the previous turn step.
|
||||
LaneID new_first_lane_from_the_right = previous_lanes.first_lane_from_the_right;
|
||||
|
||||
// The rightmost target lanes might not be involved in the turn. Figure out
|
||||
// how many lanes are to the right and not in the turn.
|
||||
new_first_lane_from_the_right +=
|
||||
std::min(current_num_lanes_right_of_turn, current_lanes.lanes_in_turn);
|
||||
|
||||
previous_lanes = {current_lanes.lanes_in_turn, new_first_lane_from_the_right};
|
||||
};
|
||||
|
||||
// 2/ When to anticipate a left, right turn
|
||||
if (isLeftTurn(current_inst))
|
||||
anticipate_for_left_turn();
|
||||
else if (is_straight_right.count(¤t) > 0)
|
||||
else if (isRightTurn(current_inst))
|
||||
anticipate_for_right_turn();
|
||||
else // FIXME: right-sided driving
|
||||
anticipate_for_right_turn();
|
||||
}
|
||||
else // keepStraight
|
||||
{
|
||||
// Heuristic: we do not have a from-lanes -> to-lanes mapping. What we use
|
||||
// here instead in addition is the number of all lanes (not only the lanes
|
||||
// in a turn):
|
||||
//
|
||||
// -v-v v-v- straight follows
|
||||
// | | | |
|
||||
// <- v v -> keep straight here
|
||||
// | |
|
||||
// <-| |->
|
||||
//
|
||||
// A route from the top left to the bottom right here goes over a keep
|
||||
// straight. If we handle all keep straights as right turns (in right-sided
|
||||
// driving), we wrongly guide the user to the rightmost lanes in the first turn.
|
||||
// Not only is this wrong but the opposite of what we expect.
|
||||
//
|
||||
// The following implements a heuristic to determine a keep straight's
|
||||
// direction in relation to the next step. In the above example we would get:
|
||||
//
|
||||
// coming from right, going to left (in direction of way) -> handle as left turn
|
||||
|
||||
if (previous_inst.type == TurnType::Suppressed &&
|
||||
current_inst.type == TurnType::Suppressed && previous.mode == current.mode &&
|
||||
previous_lanes == current_lanes)
|
||||
{
|
||||
previous.ElongateBy(current);
|
||||
current.Invalidate();
|
||||
}
|
||||
});
|
||||
if (is_straight_left.count(¤t) > 0)
|
||||
anticipate_for_left_turn();
|
||||
else if (is_straight_right.count(¤t) > 0)
|
||||
anticipate_for_right_turn();
|
||||
else // FIXME: right-sided driving
|
||||
anticipate_for_right_turn();
|
||||
}
|
||||
|
||||
if (previous_inst.type == TurnType::Suppressed &&
|
||||
current_inst.type == TurnType::Suppressed && previous.mode == current.mode &&
|
||||
previous_lanes == current_lanes)
|
||||
{
|
||||
previous.ElongateBy(current);
|
||||
current.Invalidate();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
std::for_each(begin(quick_lanes_ranges), end(quick_lanes_ranges), constrain_lanes);
|
||||
|
||||
@@ -77,7 +77,8 @@ void processRoundaboutExits(const RouteStepIterator begin, const RouteStepIterat
|
||||
return;
|
||||
}
|
||||
|
||||
const auto passes_exit_or_leaves_roundabout = [](auto const &step) {
|
||||
const auto passes_exit_or_leaves_roundabout = [](auto const &step)
|
||||
{
|
||||
return staysOnRoundabout(step.maneuver.instruction) ||
|
||||
leavesRoundabout(step.maneuver.instruction);
|
||||
};
|
||||
@@ -142,9 +143,8 @@ void processRoundaboutExits(const RouteStepIterator begin, const RouteStepIterat
|
||||
// instructions in between
|
||||
void processRoundaboutGroups(const std::pair<RouteStepIterator, RouteStepIterator> &range)
|
||||
{
|
||||
const auto leaves_roundabout = [](auto const &step) {
|
||||
return leavesRoundabout(step.maneuver.instruction);
|
||||
};
|
||||
const auto leaves_roundabout = [](auto const &step)
|
||||
{ return leavesRoundabout(step.maneuver.instruction); };
|
||||
|
||||
auto itr = range.first;
|
||||
while (itr != range.second)
|
||||
@@ -174,9 +174,8 @@ void processRoundaboutGroups(const std::pair<RouteStepIterator, RouteStepIterato
|
||||
std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps)
|
||||
{
|
||||
// check if a step has roundabout type
|
||||
const auto has_roundabout_type = [](auto const &step) {
|
||||
return hasRoundaboutType(step.maneuver.instruction);
|
||||
};
|
||||
const auto has_roundabout_type = [](auto const &step)
|
||||
{ return hasRoundaboutType(step.maneuver.instruction); };
|
||||
const auto first_roundabout_type =
|
||||
std::find_if(steps.begin(), steps.end(), has_roundabout_type);
|
||||
|
||||
@@ -193,7 +192,8 @@ std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps)
|
||||
// this group by paradigm does might contain intermediate roundabout instructions, when they are
|
||||
// directly connected. Otherwise it will be a sequence containing everything from enter to exit.
|
||||
// If we already start on the roundabout, the first valid place will be steps.begin().
|
||||
const auto is_on_roundabout = [¤tly_on_roundabout](const auto &step) {
|
||||
const auto is_on_roundabout = [¤tly_on_roundabout](const auto &step)
|
||||
{
|
||||
if (currently_on_roundabout)
|
||||
{
|
||||
if (leavesRoundabout(step.maneuver.instruction))
|
||||
@@ -327,10 +327,13 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
|
||||
}
|
||||
|
||||
// and update the leg geometry indices for the removed entry
|
||||
std::for_each(steps.begin(), steps.end(), [offset](RouteStep &step) {
|
||||
step.geometry_begin -= offset;
|
||||
step.geometry_end -= offset;
|
||||
});
|
||||
std::for_each(steps.begin(),
|
||||
steps.end(),
|
||||
[offset](RouteStep &step)
|
||||
{
|
||||
step.geometry_begin -= offset;
|
||||
step.geometry_end -= offset;
|
||||
});
|
||||
|
||||
auto &first_step = steps.front();
|
||||
auto bearing = first_bearing;
|
||||
@@ -645,16 +648,18 @@ void applyOverrides(const datafacade::BaseDataFacade &facade,
|
||||
auto step_to_update = std::find_if(
|
||||
current_step_it,
|
||||
route_iter,
|
||||
[&leg_geometry, &via_node_coords](const auto &step) {
|
||||
[&leg_geometry, &via_node_coords](const auto &step)
|
||||
{
|
||||
util::Log(logDEBUG) << "Leg geom from " << step.geometry_begin << " to "
|
||||
<< step.geometry_end << std::endl;
|
||||
|
||||
// iterators over geometry of current step
|
||||
auto begin = leg_geometry.locations.begin() + step.geometry_begin;
|
||||
auto end = leg_geometry.locations.begin() + step.geometry_end;
|
||||
auto via_match = std::find_if(begin, end, [&](const auto &location) {
|
||||
return location == via_node_coords;
|
||||
});
|
||||
auto via_match = std::find_if(begin,
|
||||
end,
|
||||
[&](const auto &location)
|
||||
{ return location == via_node_coords; });
|
||||
if (via_match != end)
|
||||
{
|
||||
util::Log(logDEBUG)
|
||||
|
||||
@@ -15,19 +15,20 @@ std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps)
|
||||
return steps;
|
||||
|
||||
// we remove only name changes that don't offer additional information
|
||||
const auto name_change_without_lanes = [](const RouteStep &step) {
|
||||
return hasTurnType(step, TurnType::NewName) && !hasLanes(step);
|
||||
};
|
||||
const auto name_change_without_lanes = [](const RouteStep &step)
|
||||
{ return hasTurnType(step, TurnType::NewName) && !hasLanes(step); };
|
||||
|
||||
// check if the next step is not important enough to announce
|
||||
const auto can_be_extended_to = [](const RouteStep &step) {
|
||||
const auto can_be_extended_to = [](const RouteStep &step)
|
||||
{
|
||||
const auto is_not_arrive = !hasWaypointType(step);
|
||||
const auto is_silent = !hasTurnType(step) || hasTurnType(step, TurnType::Suppressed);
|
||||
|
||||
return is_not_arrive && is_silent;
|
||||
};
|
||||
|
||||
const auto suppress = [](RouteStep &from_step, RouteStep &onto_step) {
|
||||
const auto suppress = [](RouteStep &from_step, RouteStep &onto_step)
|
||||
{
|
||||
from_step.ElongateBy(onto_step);
|
||||
onto_step.Invalidate();
|
||||
};
|
||||
@@ -36,28 +37,29 @@ std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps)
|
||||
// only available for a very short time
|
||||
const auto reduce_verbosity_if_possible =
|
||||
[suppress, can_be_extended_to](RouteStepIterator ¤t_turn_itr,
|
||||
RouteStepIterator &previous_turn_itr) {
|
||||
if (haveSameName(*previous_turn_itr, *current_turn_itr))
|
||||
RouteStepIterator &previous_turn_itr)
|
||||
{
|
||||
if (haveSameName(*previous_turn_itr, *current_turn_itr))
|
||||
suppress(*previous_turn_itr, *current_turn_itr);
|
||||
else
|
||||
{
|
||||
// remember the location of the name change so we can advance the previous turn
|
||||
const auto location_of_name_change = current_turn_itr;
|
||||
auto distance = current_turn_itr->distance;
|
||||
// sum up all distances that can be relevant to the name change
|
||||
while (can_be_extended_to(*(current_turn_itr + 1)) &&
|
||||
distance < NAME_SEGMENT_CUTOFF_LENGTH)
|
||||
{
|
||||
++current_turn_itr;
|
||||
distance += current_turn_itr->distance;
|
||||
}
|
||||
|
||||
if (distance < NAME_SEGMENT_CUTOFF_LENGTH)
|
||||
suppress(*previous_turn_itr, *current_turn_itr);
|
||||
else
|
||||
{
|
||||
// remember the location of the name change so we can advance the previous turn
|
||||
const auto location_of_name_change = current_turn_itr;
|
||||
auto distance = current_turn_itr->distance;
|
||||
// sum up all distances that can be relevant to the name change
|
||||
while (can_be_extended_to(*(current_turn_itr + 1)) &&
|
||||
distance < NAME_SEGMENT_CUTOFF_LENGTH)
|
||||
{
|
||||
++current_turn_itr;
|
||||
distance += current_turn_itr->distance;
|
||||
}
|
||||
|
||||
if (distance < NAME_SEGMENT_CUTOFF_LENGTH)
|
||||
suppress(*previous_turn_itr, *current_turn_itr);
|
||||
else
|
||||
previous_turn_itr = location_of_name_change;
|
||||
}
|
||||
};
|
||||
previous_turn_itr = location_of_name_change;
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_ASSERT(!hasTurnType(steps.back()) && hasWaypointType(steps.back()));
|
||||
for (auto previous_turn_itr = steps.begin(), current_turn_itr = std::next(previous_turn_itr);
|
||||
|
||||
+4
-4
@@ -93,10 +93,10 @@ Hint Hint::FromBase64(const std::string &base64Hint)
|
||||
bool Hint::IsValid(const util::Coordinate new_input_coordinates,
|
||||
const datafacade::BaseDataFacade &facade) const
|
||||
{
|
||||
const auto all_valid =
|
||||
std::all_of(segment_hints.begin(), segment_hints.end(), [&](const auto &seg_hint) {
|
||||
return seg_hint.IsValid(new_input_coordinates, facade);
|
||||
});
|
||||
const auto all_valid = std::all_of(segment_hints.begin(),
|
||||
segment_hints.end(),
|
||||
[&](const auto &seg_hint)
|
||||
{ return seg_hint.IsValid(new_input_coordinates, facade); });
|
||||
if (!all_valid)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -50,7 +50,8 @@ void filterCandidates(const std::vector<util::Coordinate> &coordinates,
|
||||
// sort by forward id, then by reverse id and then by distance
|
||||
std::sort(candidates.begin(),
|
||||
candidates.end(),
|
||||
[](const PhantomNodeWithDistance &lhs, const PhantomNodeWithDistance &rhs) {
|
||||
[](const PhantomNodeWithDistance &lhs, const PhantomNodeWithDistance &rhs)
|
||||
{
|
||||
return lhs.phantom_node.forward_segment_id.id <
|
||||
rhs.phantom_node.forward_segment_id.id ||
|
||||
(lhs.phantom_node.forward_segment_id.id ==
|
||||
@@ -65,7 +66,8 @@ void filterCandidates(const std::vector<util::Coordinate> &coordinates,
|
||||
auto new_end =
|
||||
std::unique(candidates.begin(),
|
||||
candidates.end(),
|
||||
[](const PhantomNodeWithDistance &lhs, const PhantomNodeWithDistance &rhs) {
|
||||
[](const PhantomNodeWithDistance &lhs, const PhantomNodeWithDistance &rhs)
|
||||
{
|
||||
return lhs.phantom_node.forward_segment_id.id ==
|
||||
rhs.phantom_node.forward_segment_id.id &&
|
||||
lhs.phantom_node.reverse_segment_id.id ==
|
||||
@@ -95,9 +97,8 @@ void filterCandidates(const std::vector<util::Coordinate> &coordinates,
|
||||
// sort by distance to make pruning effective
|
||||
std::sort(candidates.begin(),
|
||||
candidates.end(),
|
||||
[](const PhantomNodeWithDistance &lhs, const PhantomNodeWithDistance &rhs) {
|
||||
return lhs.distance < rhs.distance;
|
||||
});
|
||||
[](const PhantomNodeWithDistance &lhs, const PhantomNodeWithDistance &rhs)
|
||||
{ return lhs.distance < rhs.distance; });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +134,8 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
|
||||
if (max_radius_map_matching > 0 && std::any_of(parameters.radiuses.begin(),
|
||||
parameters.radiuses.end(),
|
||||
[&](const auto &radius) {
|
||||
[&](const auto &radius)
|
||||
{
|
||||
if (!radius)
|
||||
return false;
|
||||
return *radius > max_radius_map_matching;
|
||||
@@ -192,7 +194,8 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
tidied.parameters.radiuses.begin(),
|
||||
tidied.parameters.radiuses.end(),
|
||||
search_radiuses.begin(),
|
||||
[default_radius = this->default_radius](const boost::optional<double> &maybe_radius) {
|
||||
[default_radius = this->default_radius](const boost::optional<double> &maybe_radius)
|
||||
{
|
||||
if (maybe_radius)
|
||||
{
|
||||
return *maybe_radius * RADIUS_MULTIPLIER;
|
||||
@@ -212,9 +215,8 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
||||
filterCandidates(tidied.parameters.coordinates, candidates_lists);
|
||||
if (std::all_of(candidates_lists.begin(),
|
||||
candidates_lists.end(),
|
||||
[](const std::vector<PhantomNodeWithDistance> &candidates) {
|
||||
return candidates.empty();
|
||||
}))
|
||||
[](const std::vector<PhantomNodeWithDistance> &candidates)
|
||||
{ return candidates.empty(); }))
|
||||
{
|
||||
return Error("NoSegment",
|
||||
std::string("Could not find a matching segment for any coordinate."),
|
||||
|
||||
@@ -251,7 +251,8 @@ std::vector<std::size_t> getEdgeIndex(const std::vector<RTreeLeaf> &edges)
|
||||
// as the sort condition
|
||||
std::sort(sorted_edge_indexes.begin(),
|
||||
sorted_edge_indexes.end(),
|
||||
[&edges](const std::size_t &left, const std::size_t &right) -> bool {
|
||||
[&edges](const std::size_t &left, const std::size_t &right) -> bool
|
||||
{
|
||||
return (edges[left].u != edges[right].u) ? edges[left].u < edges[right].u
|
||||
: edges[left].v < edges[right].v;
|
||||
});
|
||||
@@ -430,9 +431,8 @@ void encodeVectorTile(const DataFacadeBase &facade,
|
||||
{
|
||||
vtzero::tile_builder tile;
|
||||
|
||||
const auto get_geometry_id = [&facade](auto edge) {
|
||||
return facade.GetGeometryIndex(edge.forward_segment_id.id).id;
|
||||
};
|
||||
const auto get_geometry_id = [&facade](auto edge)
|
||||
{ return facade.GetGeometryIndex(edge.forward_segment_id.id).id; };
|
||||
|
||||
// Convert tile coordinates into mercator coordinates
|
||||
double min_mercator_lon, min_mercator_lat, max_mercator_lon, max_mercator_lat;
|
||||
|
||||
@@ -137,7 +137,8 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm
|
||||
std::vector<bool> waypoint_legs(route_parameters.coordinates.size(), false);
|
||||
std::for_each(route_parameters.waypoints.begin(),
|
||||
route_parameters.waypoints.end(),
|
||||
[&](const std::size_t waypoint_index) {
|
||||
[&](const std::size_t waypoint_index)
|
||||
{
|
||||
BOOST_ASSERT(waypoint_index < waypoint_legs.size());
|
||||
waypoint_legs[waypoint_index] = true;
|
||||
});
|
||||
@@ -156,22 +157,23 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm
|
||||
else
|
||||
{
|
||||
const auto all_in_same_component =
|
||||
[](const std::vector<PhantomNodeCandidates> &waypoint_candidates) {
|
||||
return std::any_of(waypoint_candidates.front().begin(),
|
||||
waypoint_candidates.front().end(),
|
||||
// For each of the first possible phantoms, check if all other
|
||||
// positions in the list have a phantom from the same component.
|
||||
[&](const PhantomNode &phantom) {
|
||||
const auto component_id = phantom.component.id;
|
||||
return std::all_of(
|
||||
std::next(waypoint_candidates.begin()),
|
||||
std::end(waypoint_candidates),
|
||||
[component_id](const PhantomNodeCandidates &candidates) {
|
||||
return candidatesHaveComponent(candidates,
|
||||
component_id);
|
||||
});
|
||||
});
|
||||
};
|
||||
[](const std::vector<PhantomNodeCandidates> &waypoint_candidates)
|
||||
{
|
||||
return std::any_of(waypoint_candidates.front().begin(),
|
||||
waypoint_candidates.front().end(),
|
||||
// For each of the first possible phantoms, check if all other
|
||||
// positions in the list have a phantom from the same component.
|
||||
[&](const PhantomNode &phantom)
|
||||
{
|
||||
const auto component_id = phantom.component.id;
|
||||
return std::all_of(
|
||||
std::next(waypoint_candidates.begin()),
|
||||
std::end(waypoint_candidates),
|
||||
[component_id](const PhantomNodeCandidates &candidates) {
|
||||
return candidatesHaveComponent(candidates, component_id);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
if (!all_in_same_component(snapped_phantoms))
|
||||
{
|
||||
|
||||
@@ -223,9 +223,8 @@ RandIt filterViaCandidatesByStretch(RandIt first,
|
||||
const auto stretch_weight_limit =
|
||||
(1. + parameters.kAtMostLongerBy) * from_alias<double>(weight);
|
||||
|
||||
const auto over_weight_limit = [=](const auto via) {
|
||||
return from_alias<double>(via.weight) > stretch_weight_limit;
|
||||
};
|
||||
const auto over_weight_limit = [=](const auto via)
|
||||
{ return from_alias<double>(via.weight) > stretch_weight_limit; };
|
||||
|
||||
return std::remove_if(first, last, over_weight_limit);
|
||||
}
|
||||
@@ -298,13 +297,15 @@ RandIt filterPackedPathsByCellSharing(RandIt first,
|
||||
for (const auto &edge : shortest_path.path)
|
||||
cells.insert(get_cell(std::get<1>(edge)));
|
||||
|
||||
const auto over_sharing_limit = [&](const auto &packed) {
|
||||
const auto over_sharing_limit = [&](const auto &packed)
|
||||
{
|
||||
if (packed.path.empty())
|
||||
{ // don't remove routes with single-node (empty) path
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto not_seen = [&](const PackedEdge edge) {
|
||||
const auto not_seen = [&](const PackedEdge edge)
|
||||
{
|
||||
const auto source_cell = get_cell(std::get<0>(edge));
|
||||
const auto target_cell = get_cell(std::get<1>(edge));
|
||||
return cells.count(source_cell) < 1 && cells.count(target_cell) < 1;
|
||||
@@ -364,7 +365,8 @@ RandIt filterPackedPathsByLocalOptimality(const WeightedViaNodePackedPath &path,
|
||||
BOOST_ASSERT(path.via.weight != INVALID_EDGE_WEIGHT);
|
||||
|
||||
// node == parent_in_main_heap(parent_in_side_heap(v)) -> plateaux at `node`
|
||||
const auto has_plateaux_at_node = [&](const NodeID node, const Heap &fst, const Heap &snd) {
|
||||
const auto has_plateaux_at_node = [&](const NodeID node, const Heap &fst, const Heap &snd)
|
||||
{
|
||||
BOOST_ASSERT(fst.WasInserted(node));
|
||||
auto const parent = fst.GetData(node).parent;
|
||||
return snd.WasInserted(parent) && snd.GetData(parent).parent == node;
|
||||
@@ -374,7 +376,8 @@ RandIt filterPackedPathsByLocalOptimality(const WeightedViaNodePackedPath &path,
|
||||
// tree from t overlap. An edge is part of such a plateaux around `v` if:
|
||||
// v == parent_in_reverse_search(parent_in_forward_search(v)).
|
||||
// Here we calculate the last node on the plateaux in either direction.
|
||||
const auto plateaux_end = [&](NodeID node, const Heap &fst, const Heap &snd) {
|
||||
const auto plateaux_end = [&](NodeID node, const Heap &fst, const Heap &snd)
|
||||
{
|
||||
BOOST_ASSERT(node != SPECIAL_NODEID);
|
||||
BOOST_ASSERT(fst.WasInserted(node));
|
||||
BOOST_ASSERT(snd.WasInserted(node));
|
||||
@@ -388,7 +391,8 @@ RandIt filterPackedPathsByLocalOptimality(const WeightedViaNodePackedPath &path,
|
||||
return node;
|
||||
};
|
||||
|
||||
const auto is_not_locally_optimal = [&](const auto &packed) {
|
||||
const auto is_not_locally_optimal = [&](const auto &packed)
|
||||
{
|
||||
BOOST_ASSERT(packed.via.node != path.via.node);
|
||||
BOOST_ASSERT(packed.via.weight != INVALID_EDGE_WEIGHT);
|
||||
BOOST_ASSERT(packed.via.node != SPECIAL_NODEID);
|
||||
@@ -475,14 +479,16 @@ RandIt filterUnpackedPathsBySharing(RandIt first,
|
||||
|
||||
nodes.insert(begin(shortest_path.nodes), end(shortest_path.nodes));
|
||||
|
||||
const auto over_sharing_limit = [&](auto &unpacked) {
|
||||
const auto over_sharing_limit = [&](auto &unpacked)
|
||||
{
|
||||
if (unpacked.edges.empty())
|
||||
{ // don't remove routes with single-node (empty) path
|
||||
return false;
|
||||
}
|
||||
|
||||
EdgeDuration total_duration = {0};
|
||||
const auto add_if_seen = [&](const EdgeDuration duration, const NodeID node) {
|
||||
const auto add_if_seen = [&](const EdgeDuration duration, const NodeID node)
|
||||
{
|
||||
auto node_duration = facade.GetNodeDuration(node);
|
||||
total_duration += node_duration;
|
||||
if (nodes.count(node) > 0)
|
||||
@@ -533,9 +539,8 @@ RandIt filterAnnotatedRoutesByStretch(RandIt first,
|
||||
const auto stretch_duration_limit =
|
||||
(1. + parameters.kAtMostLongerBy) * from_alias<double>(shortest_route_duration);
|
||||
|
||||
const auto over_duration_limit = [=](const auto &route) {
|
||||
return from_alias<double>(route.duration()) > stretch_duration_limit;
|
||||
};
|
||||
const auto over_duration_limit = [=](const auto &route)
|
||||
{ return from_alias<double>(route.duration()) > stretch_duration_limit; };
|
||||
|
||||
return std::remove_if(first, last, over_duration_limit);
|
||||
}
|
||||
@@ -837,9 +842,9 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
|
||||
it = filterViaCandidatesByStretch(begin(candidate_vias), it, shortest_path_weight, parameters);
|
||||
|
||||
// Pre-rank by weight; sharing filtering below then discards by similarity.
|
||||
std::sort(begin(candidate_vias), it, [](const auto lhs, const auto rhs) {
|
||||
return lhs.weight < rhs.weight;
|
||||
});
|
||||
std::sort(begin(candidate_vias),
|
||||
it,
|
||||
[](const auto lhs, const auto rhs) { return lhs.weight < rhs.weight; });
|
||||
|
||||
// Filtered and ranked candidate range
|
||||
const auto candidate_vias_first = begin(candidate_vias);
|
||||
@@ -850,7 +855,8 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
|
||||
// The recursive path unpacking below destructs heaps.
|
||||
// We need to save all packed paths from the heaps upfront.
|
||||
|
||||
const auto extract_packed_path_from_heaps = [&](WeightedViaNode via) {
|
||||
const auto extract_packed_path_from_heaps = [&](WeightedViaNode via)
|
||||
{
|
||||
auto packed_path = retrievePackedPathFromHeap(forward_heap, reverse_heap, via.node);
|
||||
|
||||
return WeightedViaNodePackedPath{via, std::move(packed_path)};
|
||||
@@ -928,9 +934,8 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &sear
|
||||
std::vector<InternalRouteResult> routes;
|
||||
routes.reserve(number_of_unpacked_paths);
|
||||
|
||||
const auto unpacked_path_to_route = [&](const WeightedViaNodeUnpackedPath &path) {
|
||||
return extractRoute(facade, path.via.weight, endpoint_candidates, path.nodes, path.edges);
|
||||
};
|
||||
const auto unpacked_path_to_route = [&](const WeightedViaNodeUnpackedPath &path)
|
||||
{ return extractRoute(facade, path.via.weight, endpoint_candidates, path.nodes, path.edges); };
|
||||
|
||||
std::transform(unpacked_paths_first,
|
||||
unpacked_paths_last,
|
||||
|
||||
@@ -45,15 +45,16 @@ InternalRouteResult directShortestPathSearch(SearchEngineData<ch::Algorithm> &en
|
||||
unpacked_nodes.reserve(packed_leg.size());
|
||||
unpacked_edges.reserve(packed_leg.size());
|
||||
unpacked_nodes.push_back(packed_leg.front());
|
||||
ch::unpackPath(facade,
|
||||
packed_leg.begin(),
|
||||
packed_leg.end(),
|
||||
[&unpacked_nodes, &unpacked_edges](std::pair<NodeID, NodeID> &edge,
|
||||
const auto &edge_id) {
|
||||
BOOST_ASSERT(edge.first == unpacked_nodes.back());
|
||||
unpacked_nodes.push_back(edge.second);
|
||||
unpacked_edges.push_back(edge_id);
|
||||
});
|
||||
ch::unpackPath(
|
||||
facade,
|
||||
packed_leg.begin(),
|
||||
packed_leg.end(),
|
||||
[&unpacked_nodes, &unpacked_edges](std::pair<NodeID, NodeID> &edge, const auto &edge_id)
|
||||
{
|
||||
BOOST_ASSERT(edge.first == unpacked_nodes.back());
|
||||
unpacked_nodes.push_back(edge.second);
|
||||
unpacked_edges.push_back(edge_id);
|
||||
});
|
||||
}
|
||||
|
||||
return extractRoute(facade, weight, endpoint_candidates, unpacked_nodes, unpacked_edges);
|
||||
|
||||
@@ -95,7 +95,7 @@ void relaxOutgoingEdges(
|
||||
const DataFacade<mld::Algorithm> &facade,
|
||||
const typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap::HeapNode &heapNode,
|
||||
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||
const Args &... args)
|
||||
const Args &...args)
|
||||
{
|
||||
BOOST_ASSERT(!facade.ExcludeNode(heapNode.node));
|
||||
|
||||
@@ -280,49 +280,51 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||
|
||||
// Check if node is in the destinations list and update weights/durations
|
||||
auto update_values =
|
||||
[&](NodeID node, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance) {
|
||||
auto candidates = target_nodes_index.equal_range(node);
|
||||
for (auto it = candidates.first; it != candidates.second;)
|
||||
[&](NodeID node, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance)
|
||||
{
|
||||
auto candidates = target_nodes_index.equal_range(node);
|
||||
for (auto it = candidates.first; it != candidates.second;)
|
||||
{
|
||||
std::size_t index;
|
||||
EdgeWeight target_weight;
|
||||
EdgeDuration target_duration;
|
||||
EdgeDistance target_distance;
|
||||
std::tie(index, target_weight, target_duration, target_distance) = it->second;
|
||||
|
||||
const auto path_weight = weight + target_weight;
|
||||
if (path_weight >= EdgeWeight{0})
|
||||
{
|
||||
std::size_t index;
|
||||
EdgeWeight target_weight;
|
||||
EdgeDuration target_duration;
|
||||
EdgeDistance target_distance;
|
||||
std::tie(index, target_weight, target_duration, target_distance) = it->second;
|
||||
const auto path_duration = duration + target_duration;
|
||||
const auto path_distance = distance + target_distance;
|
||||
|
||||
const auto path_weight = weight + target_weight;
|
||||
if (path_weight >= EdgeWeight{0})
|
||||
EdgeDistance nulldistance = {0};
|
||||
auto ¤t_distance =
|
||||
distances_table.empty() ? nulldistance : distances_table[index];
|
||||
|
||||
if (std::tie(path_weight, path_duration, path_distance) <
|
||||
std::tie(weights_table[index], durations_table[index], current_distance))
|
||||
{
|
||||
const auto path_duration = duration + target_duration;
|
||||
const auto path_distance = distance + target_distance;
|
||||
|
||||
EdgeDistance nulldistance = {0};
|
||||
auto ¤t_distance =
|
||||
distances_table.empty() ? nulldistance : distances_table[index];
|
||||
|
||||
if (std::tie(path_weight, path_duration, path_distance) <
|
||||
std::tie(weights_table[index], durations_table[index], current_distance))
|
||||
{
|
||||
weights_table[index] = path_weight;
|
||||
durations_table[index] = path_duration;
|
||||
current_distance = path_distance;
|
||||
middle_nodes_table[index] = node;
|
||||
}
|
||||
|
||||
// Remove node from destinations list
|
||||
it = target_nodes_index.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
weights_table[index] = path_weight;
|
||||
durations_table[index] = path_duration;
|
||||
current_distance = path_distance;
|
||||
middle_nodes_table[index] = node;
|
||||
}
|
||||
|
||||
// Remove node from destinations list
|
||||
it = target_nodes_index.erase(it);
|
||||
}
|
||||
};
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto insert_node = [&](NodeID node,
|
||||
EdgeWeight initial_weight,
|
||||
EdgeDuration initial_duration,
|
||||
EdgeDistance initial_distance) {
|
||||
EdgeDistance initial_distance)
|
||||
{
|
||||
if (target_nodes_index.count(node))
|
||||
{
|
||||
// Source and target on the same edge node. If target is not reachable directly via
|
||||
|
||||
@@ -83,7 +83,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
|
||||
const bool use_timestamps = trace_timestamps.size() > 1;
|
||||
|
||||
const auto median_sample_time = [&] {
|
||||
const auto median_sample_time = [&]
|
||||
{
|
||||
if (use_timestamps)
|
||||
{
|
||||
return std::max(1u, getMedianSampleTime(trace_timestamps));
|
||||
@@ -104,9 +105,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
std::transform(candidates_list[t].begin(),
|
||||
candidates_list[t].end(),
|
||||
emission_log_probabilities[t].begin(),
|
||||
[&](const PhantomNodeWithDistance &candidate) {
|
||||
return default_emission_log_probability(candidate.distance);
|
||||
});
|
||||
[&](const PhantomNodeWithDistance &candidate)
|
||||
{ return default_emission_log_probability(candidate.distance); });
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -118,22 +118,19 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
{
|
||||
map_matching::EmissionLogProbability emission_log_probability(
|
||||
*trace_gps_precision[t]);
|
||||
std::transform(
|
||||
candidates_list[t].begin(),
|
||||
candidates_list[t].end(),
|
||||
emission_log_probabilities[t].begin(),
|
||||
[&emission_log_probability](const PhantomNodeWithDistance &candidate) {
|
||||
return emission_log_probability(candidate.distance);
|
||||
});
|
||||
std::transform(candidates_list[t].begin(),
|
||||
candidates_list[t].end(),
|
||||
emission_log_probabilities[t].begin(),
|
||||
[&emission_log_probability](const PhantomNodeWithDistance &candidate)
|
||||
{ return emission_log_probability(candidate.distance); });
|
||||
}
|
||||
else
|
||||
{
|
||||
std::transform(candidates_list[t].begin(),
|
||||
candidates_list[t].end(),
|
||||
emission_log_probabilities[t].begin(),
|
||||
[&](const PhantomNodeWithDistance &candidate) {
|
||||
return default_emission_log_probability(candidate.distance);
|
||||
});
|
||||
[&](const PhantomNodeWithDistance &candidate)
|
||||
{ return default_emission_log_probability(candidate.distance); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,7 +155,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
for (auto t = initial_timestamp + 1; t < candidates_list.size(); ++t)
|
||||
{
|
||||
|
||||
const auto step_time = [&] {
|
||||
const auto step_time = [&]
|
||||
{
|
||||
if (use_timestamps)
|
||||
{
|
||||
return trace_timestamps[t] - trace_timestamps[prev_unbroken_timestamps.back()];
|
||||
@@ -169,7 +167,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
}
|
||||
}();
|
||||
|
||||
const auto max_distance_delta = [&] {
|
||||
const auto max_distance_delta = [&]
|
||||
{
|
||||
if (use_timestamps)
|
||||
{
|
||||
return step_time * facade.GetMapMatchingMaxSpeed();
|
||||
@@ -180,7 +179,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
}
|
||||
}();
|
||||
|
||||
const bool gap_in_trace = [&]() {
|
||||
const bool gap_in_trace = [&]()
|
||||
{
|
||||
// use temporal information if available to determine a split
|
||||
// but do not determine split by timestamps if wasn't asked about it
|
||||
if (use_timestamps && allow_splitting)
|
||||
@@ -419,7 +419,8 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
||||
util::for_each_pair(
|
||||
reconstructed_indices,
|
||||
[&trace_distance, &trace_coordinates](const std::pair<std::size_t, std::size_t> &prev,
|
||||
const std::pair<std::size_t, std::size_t> &curr) {
|
||||
const std::pair<std::size_t, std::size_t> &curr)
|
||||
{
|
||||
trace_distance += util::coordinate_calculation::greatCircleDistance(
|
||||
trace_coordinates[prev.first], trace_coordinates[curr.first]);
|
||||
});
|
||||
|
||||
@@ -25,9 +25,8 @@ std::vector<NodeID> getForwardLoopNodes(const PhantomEndpointCandidates &endpoin
|
||||
auto requires_loop =
|
||||
std::any_of(endpoint_candidates.target_phantoms.begin(),
|
||||
endpoint_candidates.target_phantoms.end(),
|
||||
[&](const auto &target_phantom) {
|
||||
return requiresForwardLoop(source_phantom, target_phantom);
|
||||
});
|
||||
[&](const auto &target_phantom)
|
||||
{ return requiresForwardLoop(source_phantom, target_phantom); });
|
||||
if (requires_loop)
|
||||
{
|
||||
res.push_back(source_phantom.forward_segment_id.id);
|
||||
@@ -57,9 +56,8 @@ std::vector<NodeID> getBackwardLoopNodes(const PhantomEndpointCandidates &endpoi
|
||||
auto requires_loop =
|
||||
std::any_of(endpoint_candidates.target_phantoms.begin(),
|
||||
endpoint_candidates.target_phantoms.end(),
|
||||
[&](const auto &target_phantom) {
|
||||
return requiresBackwardLoop(source_phantom, target_phantom);
|
||||
});
|
||||
[&](const auto &target_phantom)
|
||||
{ return requiresBackwardLoop(source_phantom, target_phantom); });
|
||||
if (requires_loop)
|
||||
{
|
||||
res.push_back(source_phantom.reverse_segment_id.id);
|
||||
@@ -86,7 +84,8 @@ PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candid
|
||||
{
|
||||
auto source_it = std::find_if(candidates.source_phantoms.begin(),
|
||||
candidates.source_phantoms.end(),
|
||||
[&path](const auto &source_phantom) {
|
||||
[&path](const auto &source_phantom)
|
||||
{
|
||||
return path.front() == source_phantom.forward_segment_id.id ||
|
||||
path.front() == source_phantom.reverse_segment_id.id;
|
||||
});
|
||||
@@ -94,7 +93,8 @@ PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candid
|
||||
|
||||
auto target_it = std::find_if(candidates.target_phantoms.begin(),
|
||||
candidates.target_phantoms.end(),
|
||||
[&path](const auto &target_phantom) {
|
||||
[&path](const auto &target_phantom)
|
||||
{
|
||||
return path.back() == target_phantom.forward_segment_id.id ||
|
||||
path.back() == target_phantom.reverse_segment_id.id;
|
||||
});
|
||||
|
||||
@@ -19,9 +19,8 @@ void unpackEdge(const DataFacade<Algorithm> &facade,
|
||||
unpackPath(facade,
|
||||
path.begin(),
|
||||
path.end(),
|
||||
[&unpacked_path](const std::pair<NodeID, NodeID> &edge, const auto & /* data */) {
|
||||
unpacked_path.emplace_back(edge.first);
|
||||
});
|
||||
[&unpacked_path](const std::pair<NodeID, NodeID> &edge, const auto & /* data */)
|
||||
{ unpacked_path.emplace_back(edge.first); });
|
||||
unpacked_path.emplace_back(to);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,8 @@ std::vector<TurnData> generateTurns(const datafacade &facade,
|
||||
// it saves us a bunch of re-allocations during iteration.
|
||||
directed_graph.reserve(edges.size() * 2);
|
||||
|
||||
const auto get_geometry_id = [&facade](auto edge) {
|
||||
return facade.GetGeometryIndex(edge.forward_segment_id.id).id;
|
||||
};
|
||||
const auto get_geometry_id = [&facade](auto edge)
|
||||
{ return facade.GetGeometryIndex(edge.forward_segment_id.id).id; };
|
||||
|
||||
// To build a tile, we can only rely on the r-tree to quickly find all data visible within the
|
||||
// tile itself. The Rtree returns a series of segments that may or may not offer turns
|
||||
@@ -215,10 +214,10 @@ std::vector<TurnData> getTileTurns(const DataFacade<ch::Algorithm> &facade,
|
||||
//
|
||||
// would offer a backward edge at `b` to `a` (due to the oneway from a to b)
|
||||
// but could also offer a shortcut (b-c-a) from `b` to `a` which is longer.
|
||||
EdgeID edge_id = facade.FindSmallestEdge(
|
||||
approach_node, exit_node, [](const contractor::QueryEdge::EdgeData &data) {
|
||||
return data.forward && !data.shortcut;
|
||||
});
|
||||
EdgeID edge_id = facade.FindSmallestEdge(approach_node,
|
||||
exit_node,
|
||||
[](const contractor::QueryEdge::EdgeData &data)
|
||||
{ return data.forward && !data.shortcut; });
|
||||
|
||||
// Depending on how the graph is constructed, we might have to look for
|
||||
// a backwards edge instead. They're equivalent, just one is available for
|
||||
@@ -227,10 +226,10 @@ std::vector<TurnData> getTileTurns(const DataFacade<ch::Algorithm> &facade,
|
||||
// If we didn't find a forward edge, try for a backward one
|
||||
if (SPECIAL_EDGEID == edge_id)
|
||||
{
|
||||
edge_id = facade.FindSmallestEdge(
|
||||
exit_node, approach_node, [](const contractor::QueryEdge::EdgeData &data) {
|
||||
return data.backward && !data.shortcut;
|
||||
});
|
||||
edge_id = facade.FindSmallestEdge(exit_node,
|
||||
approach_node,
|
||||
[](const contractor::QueryEdge::EdgeData &data)
|
||||
{ return data.backward && !data.shortcut; });
|
||||
}
|
||||
|
||||
BOOST_ASSERT_MSG(edge_id == SPECIAL_EDGEID || !facade.GetEdgeData(edge_id).shortcut,
|
||||
|
||||
Reference in New Issue
Block a user