refactor route step / intermediate intersections

rename intersection (engine version) to IntermediateIntersection
follow coding convention for existing functions, move invalidate into routeStep
moved elongate into route step
move forward-step-signage into route step
replace post-processings `forwardInto` with `RouteStep` functionality. Don't change maneuver in step
separete declaration and implementation
This commit is contained in:
Moritz Kobitzsch 2016-12-20 14:57:08 +01:00
parent 3cbac0f012
commit bc081b7132
11 changed files with 230 additions and 234 deletions

View File

@ -302,16 +302,16 @@ class GraphContractor
util::UnbufferedLog log; util::UnbufferedLog log;
log << "initializing elimination PQ ..."; log << "initializing elimination PQ ...";
tbb::parallel_for( tbb::parallel_for(tbb::blocked_range<NodeID>(0, number_of_nodes, PQGrainSize),
tbb::blocked_range<NodeID>(0, number_of_nodes, PQGrainSize), [this, &node_priorities, &node_depth, &thread_data_list](
[this, &node_priorities, &node_depth, &thread_data_list]( const tbb::blocked_range<NodeID> &range) {
const tbb::blocked_range<NodeID> &range) { ContractorThreadData *data = thread_data_list.GetThreadData();
ContractorThreadData *data = thread_data_list.GetThreadData(); for (auto x = range.begin(), end = range.end(); x != end; ++x)
for (auto x = range.begin(), end = range.end(); x != end; ++x) {
{ node_priorities[x] =
node_priorities[x] = this->EvaluateNodePriority(data, node_depth[x], x); this->EvaluateNodePriority(data, node_depth[x], x);
} }
}); });
log << "ok"; log << "ok";
} }
BOOST_ASSERT(node_priorities.size() == number_of_nodes); BOOST_ASSERT(node_priorities.size() == number_of_nodes);
@ -552,8 +552,7 @@ class GraphContractor
[this, &node_priorities, &remaining_nodes, &node_depth, &thread_data_list]( [this, &node_priorities, &remaining_nodes, &node_depth, &thread_data_list](
const tbb::blocked_range<NodeID> &range) { const tbb::blocked_range<NodeID> &range) {
ContractorThreadData *data = thread_data_list.GetThreadData(); ContractorThreadData *data = thread_data_list.GetThreadData();
for (auto position = range.begin(), end = range.end(); for (auto position = range.begin(), end = range.end(); position != end;
position != end;
++position) ++position)
{ {
NodeID x = remaining_nodes[position].id; NodeID x = remaining_nodes[position].id;

View File

@ -70,13 +70,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
WaypointType::Depart, WaypointType::Depart,
0}; 0};
Intersection intersection{source_node.location, IntermediateIntersection intersection{source_node.location,
std::vector<short>({bearings.second}), std::vector<short>({bearings.second}),
std::vector<bool>({true}), std::vector<bool>({true}),
Intersection::NO_INDEX, IntermediateIntersection::NO_INDEX,
0, 0,
util::guidance::LaneTuple(), util::guidance::LaneTuple(),
{}}; {}};
if (leg_data.size() > 0) if (leg_data.size() > 0)
{ {
@ -218,7 +218,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
std::vector<short>({static_cast<short>(util::reverseBearing(bearings.first))}), std::vector<short>({static_cast<short>(util::reverseBearing(bearings.first))}),
std::vector<bool>({true}), std::vector<bool>({true}),
0, 0,
Intersection::NO_INDEX, IntermediateIntersection::NO_INDEX,
util::guidance::LaneTuple(), util::guidance::LaneTuple(),
{}}; {}};

View File

@ -30,10 +30,6 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps);
// maneuvers that can, in some form, be seen as one. Lookahead of one step. // maneuvers that can, in some form, be seen as one. Lookahead of one step.
bool collapsable(const RouteStep &step, const RouteStep &next); bool collapsable(const RouteStep &step, const RouteStep &next);
// Elongate a step by another. the data is added either at the front, or the back
OSRM_ATTR_WARN_UNUSED
RouteStep elongate(RouteStep step, const RouteStep &by_step);
// trim initial/final segment of very short length. // trim initial/final segment of very short length.
// This function uses in/out parameter passing to modify both steps and geometry in place. // This function uses in/out parameter passing to modify both steps and geometry in place.
// We use this method since both steps and geometry are closely coupled logically but // We use this method since both steps and geometry are closely coupled logically but

View File

@ -30,7 +30,7 @@ namespace guidance
// Arrive: a --> b --> t. The segment (b,t) is already covered by the previous segment. // Arrive: a --> b --> t. The segment (b,t) is already covered by the previous segment.
// A representation of intermediate intersections // A representation of intermediate intersections
struct Intersection struct IntermediateIntersection
{ {
static const constexpr std::size_t NO_INDEX = std::numeric_limits<std::size_t>::max(); static const constexpr std::size_t NO_INDEX = std::numeric_limits<std::size_t>::max();
util::Coordinate location; util::Coordinate location;
@ -44,13 +44,13 @@ struct Intersection
extractor::guidance::TurnLaneDescription lane_description; extractor::guidance::TurnLaneDescription lane_description;
}; };
inline Intersection getInvalidIntersection() inline IntermediateIntersection getInvalidIntersection()
{ {
return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}}, return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}},
{}, {},
{}, {},
Intersection::NO_INDEX, IntermediateIntersection::NO_INDEX,
Intersection::NO_INDEX, IntermediateIntersection::NO_INDEX,
util::guidance::LaneTuple(), util::guidance::LaneTuple(),
{}}; {}};
} }
@ -71,55 +71,135 @@ struct RouteStep
// indices into the locations array stored the LegGeometry // indices into the locations array stored the LegGeometry
std::size_t geometry_begin; std::size_t geometry_begin;
std::size_t geometry_end; std::size_t geometry_end;
std::vector<Intersection> intersections; std::vector<IntermediateIntersection> intersections;
LaneID numLanesToTheRight() const // remove all information from the route step, marking it as invalid (used to indicate empty
{ // steps to be removed).
return intersections.front().lanes.first_lane_from_the_right; void Invalidate();
}
LaneID numLanesToTheLeft() const // Elongate by another step in front
{ RouteStep &AddInFront(const RouteStep &preceeding_step);
LaneID const total = intersections.front().lane_description.size();
return total - (intersections.front().lanes.lanes_in_turn +
intersections.front().lanes.first_lane_from_the_right);
}
auto lanesToTheLeft() const // Elongate by another step in back
{ RouteStep &ElongateBy(const RouteStep &following_step);
const auto &description = intersections.front().lane_description;
LaneID num_lanes_left = numLanesToTheLeft();
return boost::make_iterator_range(description.begin(),
description.begin() + num_lanes_left);
}
auto lanesToTheRight() const /* Elongate without prior knowledge of in front, or in back, convenience function if you
{ * don't know if step is augmented in front or at the back */
const auto &description = intersections.front().lane_description; RouteStep &MergeWith(const RouteStep &by_step);
LaneID num_lanes_right = numLanesToTheRight();
return boost::make_iterator_range(description.end() - num_lanes_right, description.end()); // copy all strings from origin into the step, apart from rotary names
} RouteStep &AdaptStepSignage(const RouteStep &origin);
LaneID NumLanesToTheRight() const;
LaneID NumLanesToTheLeft() const;
auto LanesToTheLeft() const;
auto LanesToTheRight() const;
}; };
inline RouteStep getInvalidRouteStep() inline void RouteStep::Invalidate()
{ {
return {0, name_id = EMPTY_NAMEID;
"", name.clear();
"", ref.clear();
"", pronunciation.clear();
"", destinations.clear();
"", rotary_name.clear();
"", rotary_pronunciation.clear();
0, duration = 0;
0, distance = 0;
TRAVEL_MODE_INACCESSIBLE, mode = TRAVEL_MODE_INACCESSIBLE;
getInvalidStepManeuver(), maneuver = getInvalidStepManeuver();
0, geometry_begin = 0;
0, geometry_end = 0;
{getInvalidIntersection()}}; intersections.clear();
} intersections.push_back(getInvalidIntersection());
}
}
} }
// Elongate by another step in front
inline RouteStep &RouteStep::AddInFront(const RouteStep &preceeding_step)
{
BOOST_ASSERT(preceeding_step.geometry_end == geometry_begin + 1);
BOOST_ASSERT(mode == preceeding_step.mode);
duration += preceeding_step.duration;
distance += preceeding_step.distance;
geometry_begin = preceeding_step.geometry_begin;
intersections.insert(intersections.begin(),
preceeding_step.intersections.begin(),
preceeding_step.intersections.end());
return *this;
}
// Elongate by another step in back
inline RouteStep &RouteStep::ElongateBy(const RouteStep &following_step)
{
BOOST_ASSERT(geometry_end == following_step.geometry_begin + 1);
BOOST_ASSERT(mode == following_step.mode);
duration += following_step.duration;
distance += following_step.distance;
geometry_end = following_step.geometry_end;
intersections.insert(intersections.end(),
following_step.intersections.begin(),
following_step.intersections.end());
return *this;
}
// Elongate without prior knowledge of in front, or in back.
inline RouteStep &RouteStep::MergeWith(const RouteStep &by_step)
{
// if our own geometry ends, where the next begins, we elongate by
if (geometry_end == by_step.geometry_begin + 1)
return AddInFront(by_step);
else
return ElongateBy(by_step);
}
// copy all strings from origin into the step, apart from rotary names
inline RouteStep &RouteStep::AdaptStepSignage(const RouteStep &origin)
{
name_id = origin.name_id;
name = origin.name;
pronunciation = origin.pronunciation;
destinations = origin.destinations;
ref = origin.ref;
return *this;
}
inline LaneID RouteStep::NumLanesToTheRight() const
{
return intersections.front().lanes.first_lane_from_the_right;
}
inline LaneID RouteStep::NumLanesToTheLeft() const
{
LaneID const total = intersections.front().lane_description.size();
return total - (intersections.front().lanes.lanes_in_turn +
intersections.front().lanes.first_lane_from_the_right);
}
inline auto RouteStep::LanesToTheLeft() const
{
const auto &description = intersections.front().lane_description;
LaneID num_lanes_left = NumLanesToTheLeft();
return boost::make_iterator_range(description.begin(), description.begin() + num_lanes_left);
}
inline auto RouteStep::LanesToTheRight() const
{
const auto &description = intersections.front().lane_description;
LaneID num_lanes_right = NumLanesToTheRight();
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif #endif

View File

@ -60,7 +60,7 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
maneuver.instruction.direction_modifier != DirectionModifier::UTurn); maneuver.instruction.direction_modifier != DirectionModifier::UTurn);
} }
inline bool hasValidLanes(const guidance::Intersection &intersection) inline bool hasValidLanes(const guidance::IntermediateIntersection &intersection)
{ {
return intersection.lanes.lanes_in_turn > 0; return intersection.lanes.lanes_in_turn > 0;
} }
@ -72,7 +72,7 @@ std::string instructionTypeToString(const TurnType::Enum type)
return turn_type_names[static_cast<std::size_t>(type)]; return turn_type_names[static_cast<std::size_t>(type)];
} }
util::json::Array lanesFromIntersection(const guidance::Intersection &intersection) util::json::Array lanesFromIntersection(const guidance::IntermediateIntersection &intersection)
{ {
BOOST_ASSERT(intersection.lanes.lanes_in_turn >= 1); BOOST_ASSERT(intersection.lanes.lanes_in_turn >= 1);
util::json::Array result; util::json::Array result;
@ -200,7 +200,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
return step_maneuver; return step_maneuver;
} }
util::json::Object makeIntersection(const guidance::Intersection &intersection) util::json::Object makeIntersection(const guidance::IntermediateIntersection &intersection)
{ {
util::json::Object result; util::json::Object result;
util::json::Array bearings; util::json::Array bearings;
@ -226,9 +226,9 @@ util::json::Object makeIntersection(const guidance::Intersection &intersection)
result.values["location"] = detail::coordinateToLonLat(intersection.location); result.values["location"] = detail::coordinateToLonLat(intersection.location);
result.values["bearings"] = bearings; result.values["bearings"] = bearings;
result.values["entry"] = entry; result.values["entry"] = entry;
if (intersection.in != guidance::Intersection::NO_INDEX) if (intersection.in != guidance::IntermediateIntersection::NO_INDEX)
result.values["in"] = intersection.in; result.values["in"] = intersection.in;
if (intersection.out != guidance::Intersection::NO_INDEX) if (intersection.out != guidance::IntermediateIntersection::NO_INDEX)
result.values["out"] = intersection.out; result.values["out"] = intersection.out;
if (detail::hasValidLanes(intersection)) if (detail::hasValidLanes(intersection))

View File

@ -78,8 +78,8 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
// where lanes in the turn fan in but for example the overall lanes at that location // 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 // 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. // 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_right_of_turn = current.NumLanesToTheRight();
const LaneID current_num_lanes_left_of_turn = current.numLanesToTheLeft(); const LaneID current_num_lanes_left_of_turn = current.NumLanesToTheLeft();
const LaneID num_shared_lanes = std::min(current_lanes.lanes_in_turn, // const LaneID num_shared_lanes = std::min(current_lanes.lanes_in_turn, //
previous_lanes.lanes_in_turn); // previous_lanes.lanes_in_turn); //
@ -166,7 +166,7 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
// step as invalid, scheduled for later removal. // step as invalid, scheduled for later removal.
if (collapsable(previous, current)) if (collapsable(previous, current))
{ {
previous = elongate(previous, current); previous.ElongateBy(current);
current.maneuver.instruction = TurnInstruction::NO_TURN(); current.maneuver.instruction = TurnInstruction::NO_TURN();
} }
}); });

View File

@ -50,18 +50,6 @@ inline bool hasManeuver(const RouteStep &first, const RouteStep &second)
second.maneuver.instruction.type != TurnType::NoTurn); second.maneuver.instruction.type != TurnType::NoTurn);
} }
// forward all signage/name data from one step to another.
// When we collapse a step, we might have to transfer the name, pronunciation and similar tags.
inline void forwardStepSignage(RouteStep &destination, const RouteStep &origin)
{
destination.name_id = origin.name_id;
destination.name = origin.name;
destination.pronunciation = origin.pronunciation;
destination.destinations = origin.destinations;
destination.destinations = origin.destinations;
destination.ref = origin.ref;
}
inline bool choiceless(const RouteStep &step, const RouteStep &previous) inline bool choiceless(const RouteStep &step, const RouteStep &previous)
{ {
// if the next turn is choiceless, we consider longer turn roads collapsable than usually // if the next turn is choiceless, we consider longer turn roads collapsable than usually
@ -90,9 +78,6 @@ bool isCollapsableInstruction(const TurnInstruction instruction)
bool compatible(const RouteStep &lhs, const RouteStep &rhs) { return lhs.mode == rhs.mode; } bool compatible(const RouteStep &lhs, const RouteStep &rhs) { return lhs.mode == rhs.mode; }
// invalidate a step and set its content to nothing
void invalidateStep(RouteStep &step) { step = getInvalidRouteStep(); }
// Checks if name change happens the user wants to know about. // Checks if name change happens the user wants to know about.
// Treats e.g. "Name (Ref)" -> "Name" changes still as same name. // Treats e.g. "Name (Ref)" -> "Name" changes still as same name.
bool isNoticeableNameChange(const RouteStep &lhs, const RouteStep &rhs) bool isNoticeableNameChange(const RouteStep &lhs, const RouteStep &rhs)
@ -115,32 +100,6 @@ double nameSegmentLength(std::size_t at, const std::vector<RouteStep> &steps)
return result; return result;
} }
OSRM_ATTR_WARN_UNUSED
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
{
// Merge a turn into a silent turn
// Overwrites turn instruction and increases exit NR
destination.duration += source.duration;
destination.distance += source.distance;
destination.maneuver.exit = source.maneuver.exit;
if (destination.geometry_begin < source.geometry_begin)
{
destination.intersections.insert(destination.intersections.end(),
source.intersections.begin(),
source.intersections.end());
}
else
{
destination.intersections.insert(destination.intersections.begin(),
source.intersections.begin(),
source.intersections.end());
}
destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin);
destination.geometry_end = std::max(destination.geometry_end, source.geometry_end);
return destination;
}
void fixFinalRoundabout(std::vector<RouteStep> &steps) void fixFinalRoundabout(std::vector<RouteStep> &steps)
{ {
for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0; for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0;
@ -173,9 +132,9 @@ void fixFinalRoundabout(std::vector<RouteStep> &steps)
// TODO this operates on the data that is in the instructions. // TODO this operates on the data that is in the instructions.
// We are missing out on the final segment after the last stay-on-roundabout // We are missing out on the final segment after the last stay-on-roundabout
// instruction though. it is not contained somewhere until now // instruction though. it is not contained somewhere until now
steps[propagation_index - 1] = steps[propagation_index - 1].ElongateBy(propagation_step);
forwardInto(std::move(steps[propagation_index - 1]), propagation_step); steps[propagation_index - 1].maneuver.exit = propagation_step.maneuver.exit;
invalidateStep(propagation_step); propagation_step.Invalidate();
} }
} }
} }
@ -240,7 +199,7 @@ void closeOffRoundabout(const bool on_roundabout,
steps[1].maneuver.instruction.type == TurnType::UseLane); steps[1].maneuver.instruction.type == TurnType::UseLane);
steps[0].geometry_end = 1; steps[0].geometry_end = 1;
steps[1].geometry_begin = 0; steps[1].geometry_begin = 0;
steps[1] = forwardInto(steps[1], steps[0]); steps[1].AddInFront(steps[0]);
steps[1].intersections.erase(steps[1].intersections.begin()); // otherwise we copy the steps[1].intersections.erase(steps[1].intersections.begin()); // otherwise we copy the
// source // source
if (leavesRoundabout(steps[1].maneuver.instruction)) if (leavesRoundabout(steps[1].maneuver.instruction))
@ -282,7 +241,8 @@ void closeOffRoundabout(const bool on_roundabout,
--propagation_index) --propagation_index)
{ {
auto &propagation_step = steps[propagation_index]; auto &propagation_step = steps[propagation_index];
propagation_step = forwardInto(propagation_step, steps[propagation_index + 1]); propagation_step.ElongateBy(steps[propagation_index + 1]);
propagation_step.maneuver.exit = steps[propagation_index + 1].maneuver.exit;
if (entersRoundabout(propagation_step.maneuver.instruction)) if (entersRoundabout(propagation_step.maneuver.instruction))
{ {
const auto entry_intersection = propagation_step.intersections.front(); const auto entry_intersection = propagation_step.intersections.front();
@ -309,13 +269,13 @@ void closeOffRoundabout(const bool on_roundabout,
getTurnDirection(angle); getTurnDirection(angle);
} }
forwardStepSignage(propagation_step, destination_copy); propagation_step.AdaptStepSignage(destination_copy);
invalidateStep(steps[propagation_index + 1]); steps[propagation_index + 1].Invalidate();
break; break;
} }
else else
{ {
invalidateStep(steps[propagation_index + 1]); steps[propagation_index + 1].Invalidate();
} }
} }
// remove exit // remove exit
@ -445,19 +405,18 @@ void collapseUTurn(std::vector<RouteStep> &steps,
if (direct_u_turn || u_turn_with_name_change) if (direct_u_turn || u_turn_with_name_change)
{ {
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]); steps[one_back_index].ElongateBy(steps[step_index]);
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
if (u_turn_with_name_change) if (u_turn_with_name_change)
{ {
BOOST_ASSERT_MSG(compatible(steps[one_back_index], steps[next_step_index]), BOOST_ASSERT_MSG(compatible(steps[one_back_index], steps[next_step_index]),
"Compatibility should be transitive"); "Compatibility should be transitive");
steps[one_back_index] = steps[one_back_index].ElongateBy(steps[next_step_index]);
elongate(std::move(steps[one_back_index]), steps[next_step_index]); steps[next_step_index].Invalidate(); // will be skipped due to the
invalidateStep(steps[next_step_index]); // will be skipped due to the // continue statement at the
// continue statement at the // beginning of this function
// beginning of this function
} }
forwardStepSignage(steps[one_back_index], steps[two_back_index]); steps[one_back_index].AdaptStepSignage(steps[two_back_index]);
steps[one_back_index].maneuver.instruction.type = TurnType::Continue; steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
steps[one_back_index].maneuver.instruction.direction_modifier = DirectionModifier::UTurn; steps[one_back_index].maneuver.instruction.direction_modifier = DirectionModifier::UTurn;
} }
@ -685,15 +644,15 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
} }
} }
steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step); steps[two_back_index].ElongateBy(one_back_step);
// If the previous instruction asked to continue, the name change will have to // If the previous instruction asked to continue, the name change will have to
// be changed into a turn // be changed into a turn
invalidateStep(steps[one_back_index]); steps[one_back_index].Invalidate();
} }
// very short segment after turn, turn location remains at one_back_step // very short segment after turn, turn location remains at one_back_step
else if (isDelayedTurn(one_back_step, current_step)) // checks for compatibility else if (isDelayedTurn(one_back_step, current_step)) // checks for compatibility
{ {
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]); steps[one_back_index].ElongateBy(steps[step_index]);
// TODO check for lanes (https://github.com/Project-OSRM/osrm-backend/issues/2553) // TODO check for lanes (https://github.com/Project-OSRM/osrm-backend/issues/2553)
if (TurnType::Continue == one_back_step.maneuver.instruction.type && if (TurnType::Continue == one_back_step.maneuver.instruction.type &&
isNoticeableNameChange(steps[two_back_index], current_step)) isNoticeableNameChange(steps[two_back_index], current_step))
@ -723,7 +682,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
steps[one_back_index].maneuver.instruction.direction_modifier = steps[one_back_index].maneuver.instruction.direction_modifier =
DirectionModifier::UTurn; DirectionModifier::UTurn;
} }
forwardStepSignage(steps[one_back_index], current_step); steps[one_back_index].AdaptStepSignage(current_step);
} }
else if (TurnType::NewName == one_back_step.maneuver.instruction.type || else if (TurnType::NewName == one_back_step.maneuver.instruction.type ||
(TurnType::NewName == current_step.maneuver.instruction.type && (TurnType::NewName == current_step.maneuver.instruction.type &&
@ -749,30 +708,29 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
steps[one_back_index].name = current_step.name; steps[one_back_index].name = current_step.name;
steps[one_back_index].name_id = current_step.name_id; steps[one_back_index].name_id = current_step.name_id;
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
} }
else if (TurnType::Suppressed == current_step.maneuver.instruction.type && else if (TurnType::Suppressed == current_step.maneuver.instruction.type &&
!isNoticeableNameChange(one_back_step, current_step) && !isNoticeableNameChange(one_back_step, current_step) &&
compatible(one_back_step, current_step)) compatible(one_back_step, current_step))
{ {
steps[one_back_index] = elongate(std::move(steps[one_back_index]), current_step); steps[one_back_index].ElongateBy(current_step);
const auto angle = findTotalTurnAngle(one_back_step, current_step); const auto angle = findTotalTurnAngle(one_back_step, current_step);
steps[one_back_index].maneuver.instruction.direction_modifier = getTurnDirection(angle); steps[one_back_index].maneuver.instruction.direction_modifier = getTurnDirection(angle);
steps[step_index].Invalidate();
invalidateStep(steps[step_index]);
} }
else if (TurnType::Turn == one_back_step.maneuver.instruction.type && else if (TurnType::Turn == one_back_step.maneuver.instruction.type &&
TurnType::OnRamp == current_step.maneuver.instruction.type && TurnType::OnRamp == current_step.maneuver.instruction.type &&
compatible(one_back_step, current_step)) compatible(one_back_step, current_step))
{ {
// turning onto a ramp makes the first turn into a ramp // turning onto a ramp makes the first turn into a ramp
steps[one_back_index] = elongate(std::move(steps[one_back_index]), current_step); steps[one_back_index].ElongateBy(current_step);
steps[one_back_index].maneuver.instruction.type = TurnType::OnRamp; steps[one_back_index].maneuver.instruction.type = TurnType::OnRamp;
const auto angle = findTotalTurnAngle(one_back_step, current_step); const auto angle = findTotalTurnAngle(one_back_step, current_step);
steps[one_back_index].maneuver.instruction.direction_modifier = getTurnDirection(angle); steps[one_back_index].maneuver.instruction.direction_modifier = getTurnDirection(angle);
forwardStepSignage(steps[one_back_index], current_step); steps[one_back_index].AdaptStepSignage(current_step);
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
} }
} }
@ -864,43 +822,6 @@ bool collapsable(const RouteStep &step, const RouteStep &next)
return false; return false;
} }
// elongate a step by another. the data is added either at the front, or the back
OSRM_ATTR_WARN_UNUSED
RouteStep elongate(RouteStep step, const RouteStep &by_step)
{
BOOST_ASSERT(step.mode == by_step.mode);
step.duration += by_step.duration;
step.distance += by_step.distance;
BOOST_ASSERT(step.mode == by_step.mode);
// by_step comes after step -> we append at the end
if (step.geometry_end == by_step.geometry_begin + 1)
{
step.geometry_end = by_step.geometry_end;
// if we elongate in the back, we only need to copy the intersections to the beginning.
// the bearings remain the same, as the location of the turn doesn't change
step.intersections.insert(
step.intersections.end(), by_step.intersections.begin(), by_step.intersections.end());
}
// by_step comes before step -> we append at the front
else
{
BOOST_ASSERT(step.maneuver.waypoint_type == WaypointType::None &&
by_step.maneuver.waypoint_type == WaypointType::None);
BOOST_ASSERT(by_step.geometry_end == step.geometry_begin + 1);
step.geometry_begin = by_step.geometry_begin;
// elongating in the front changes the location of the maneuver
step.maneuver = by_step.maneuver;
step.intersections.insert(
step.intersections.begin(), by_step.intersections.begin(), by_step.intersections.end());
}
return step;
}
// Post processing can invalidate some instructions. For example StayOnRoundabout // Post processing can invalidate some instructions. For example StayOnRoundabout
// is turned into exit counts. These instructions are removed by the following function // is turned into exit counts. These instructions are removed by the following function
@ -1081,9 +1002,8 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
{ {
// Traffic light on the sliproad, the road itself will be handled in the next // Traffic light on the sliproad, the road itself will be handled in the next
// iteration, when one-back-index again points to the sliproad. // iteration, when one-back-index again points to the sliproad.
steps[one_back_index] = steps[one_back_index].ElongateBy(steps[step_index]);
elongate(std::move(steps[one_back_index]), steps[step_index]); steps[step_index].Invalidate();
invalidateStep(steps[step_index]);
} }
else else
{ {
@ -1110,10 +1030,9 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
else else
steps[one_back_index].maneuver.instruction.type = TurnType::Turn; steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
steps[one_back_index] = steps[one_back_index].ElongateBy(steps[step_index]);
elongate(std::move(steps[one_back_index]), steps[step_index]);
forwardStepSignage(steps[one_back_index], steps[step_index]); steps[one_back_index].AdaptStepSignage(steps[step_index]);
// the turn lanes for this turn are on the sliproad itself, so we have to // the turn lanes for this turn are on the sliproad itself, so we have to
// remember them // remember them
steps[one_back_index].intersections.front().lanes = steps[one_back_index].intersections.front().lanes =
@ -1124,7 +1043,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
const auto angle = findTotalTurnAngle(one_back_step, current_step); const auto angle = findTotalTurnAngle(one_back_step, current_step);
steps[one_back_index].maneuver.instruction.direction_modifier = steps[one_back_index].maneuver.instruction.direction_modifier =
getTurnDirection(angle); getTurnDirection(angle);
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
} }
else else
{ {
@ -1146,9 +1065,8 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
for (std::size_t index = last_available_name_index + 1; index <= step_index; ++index) for (std::size_t index = last_available_name_index + 1; index <= step_index; ++index)
{ {
steps[last_available_name_index] = steps[last_available_name_index].ElongateBy(steps[index]);
elongate(std::move(steps[last_available_name_index]), steps[index]); steps[index].Invalidate();
invalidateStep(steps[index]);
} }
} }
// If we look at two consecutive name changes, we can check for a name oscillation. // If we look at two consecutive name changes, we can check for a name oscillation.
@ -1166,11 +1084,11 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
{ {
if (compatible(one_back_step, steps[two_back_index])) if (compatible(one_back_step, steps[two_back_index]))
{ {
steps[two_back_index] = steps[two_back_index]
elongate(elongate(std::move(steps[two_back_index]), steps[one_back_index]), .ElongateBy(steps[one_back_index])
steps[step_index]); .ElongateBy(steps[step_index]);
invalidateStep(steps[one_back_index]); steps[one_back_index].Invalidate();
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
} }
// TODO discuss: we could think about changing the new-name to a pure notification // TODO discuss: we could think about changing the new-name to a pure notification
// about mode changes // about mode changes
@ -1180,15 +1098,13 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
{ {
if (compatible(steps[two_back_index], steps[one_back_index])) if (compatible(steps[two_back_index], steps[one_back_index]))
{ {
steps[two_back_index] = steps[two_back_index].ElongateBy(steps[one_back_index]);
elongate(std::move(steps[two_back_index]), steps[one_back_index]); steps[one_back_index].Invalidate();
invalidateStep(steps[one_back_index]);
if (nameSegmentLength(step_index, steps) < name_segment_cutoff_length && if (nameSegmentLength(step_index, steps) < name_segment_cutoff_length &&
compatible(steps[two_back_index], steps[step_index])) compatible(steps[two_back_index], steps[step_index]))
{ {
steps[two_back_index] = steps[two_back_index].ElongateBy(steps[step_index]);
elongate(std::move(steps[two_back_index]), steps[step_index]); steps[step_index].Invalidate();
invalidateStep(steps[step_index]);
} }
} }
} }
@ -1203,11 +1119,11 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
// change, // change,
// we don't wan't to collapse the initial intersection. // we don't wan't to collapse the initial intersection.
// a - b ---BRIDGE -- c // a - b ---BRIDGE -- c
steps[one_back_index] = steps[one_back_index]
elongate(std::move(steps[one_back_index]), .ElongateBy(steps[step_index])
elongate(std::move(steps[step_index]), steps[next_step_index])); .ElongateBy(steps[next_step_index]);
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
invalidateStep(steps[next_step_index]); steps[next_step_index].Invalidate();
} }
} }
else if (choiceless(current_step, one_back_step) || else if (choiceless(current_step, one_back_step) ||
@ -1350,7 +1266,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
designated_depart.intersections.front().lane_description.clear(); designated_depart.intersections.front().lane_description.clear();
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]}; first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
first_intersection.entry = {true}; first_intersection.entry = {true};
first_intersection.in = Intersection::NO_INDEX; first_intersection.in = IntermediateIntersection::NO_INDEX;
first_intersection.out = 0; first_intersection.out = 0;
// finally remove the initial (now duplicated move) // finally remove the initial (now duplicated move)
@ -1423,7 +1339,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
auto &last_intersection = next_to_last_step.intersections.back(); auto &last_intersection = next_to_last_step.intersections.back();
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]}; last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
last_intersection.entry = {true}; last_intersection.entry = {true};
last_intersection.out = Intersection::NO_INDEX; last_intersection.out = IntermediateIntersection::NO_INDEX;
last_intersection.in = 0; last_intersection.in = 0;
steps.pop_back(); steps.pop_back();
@ -1433,7 +1349,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
// as the segment before it. Thus, we have to copy the names // as the segment before it. Thus, we have to copy the names
// and travel modes from the new next_to_last step. // and travel modes from the new next_to_last step.
auto &new_next_to_last = *(steps.end() - 2); auto &new_next_to_last = *(steps.end() - 2);
forwardStepSignage(next_to_last_step, new_next_to_last); next_to_last_step.AdaptStepSignage(new_next_to_last);
next_to_last_step.mode = new_next_to_last.mode; next_to_last_step.mode = new_next_to_last.mode;
// the geometry indices of the last step are already correct; // the geometry indices of the last step are already correct;
} }
@ -1560,10 +1476,8 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
BOOST_ASSERT(compatible(steps[last_valid_instruction], step)); BOOST_ASSERT(compatible(steps[last_valid_instruction], step));
// count intersections. We cannot use exit, since intersections can follow directly // count intersections. We cannot use exit, since intersections can follow directly
// after a roundabout // after a roundabout
steps[last_valid_instruction] = steps[last_valid_instruction].ElongateBy(step);
elongate(std::move(steps[last_valid_instruction]), step); steps[step_index].Invalidate();
step.maneuver.instruction = TurnInstruction::NO_TURN();
invalidateStep(steps[step_index]);
} }
else if (!isSilent(instruction)) else if (!isSilent(instruction))
{ {
@ -1604,13 +1518,13 @@ std::vector<RouteStep> collapseUseLane(std::vector<RouteStep> steps)
// the lane description is given left to right, lanes are counted from the right. // the lane description is given left to right, lanes are counted from the right.
// Therefore we access the lane description using the reverse iterator // Therefore we access the lane description using the reverse iterator
auto right_most_lanes = step.lanesToTheRight(); auto right_most_lanes = step.LanesToTheRight();
if (!right_most_lanes.empty() && containsTag(right_most_lanes.front(), if (!right_most_lanes.empty() && containsTag(right_most_lanes.front(),
(extractor::guidance::TurnLaneType::straight | (extractor::guidance::TurnLaneType::straight |
extractor::guidance::TurnLaneType::none))) extractor::guidance::TurnLaneType::none)))
return false; return false;
auto left_most_lanes = step.lanesToTheLeft(); auto left_most_lanes = step.LanesToTheLeft();
if (!left_most_lanes.empty() && containsTag(left_most_lanes.back(), if (!left_most_lanes.empty() && containsTag(left_most_lanes.back(),
(extractor::guidance::TurnLaneType::straight | (extractor::guidance::TurnLaneType::straight |
extractor::guidance::TurnLaneType::none))) extractor::guidance::TurnLaneType::none)))
@ -1627,8 +1541,8 @@ std::vector<RouteStep> collapseUseLane(std::vector<RouteStep> steps)
const auto previous = getPreviousIndex(step_index, steps); const auto previous = getPreviousIndex(step_index, steps);
if (compatible(steps[previous], step)) if (compatible(steps[previous], step))
{ {
steps[previous] = elongate(std::move(steps[previous]), steps[step_index]); steps[previous].ElongateBy(steps[step_index]);
invalidateStep(steps[step_index]); steps[step_index].Invalidate();
} }
} }
} }

View File

@ -130,8 +130,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
// fallback, mostly necessary for dead ends // fallback, mostly necessary for dead ends
if (intersection_node == to_node) if (intersection_node == to_node)
{ {
const auto result = ExtractCoordinateAtLength( const auto result = ExtractCoordinateAtLength(skipping_inaccuracies_distance, coordinates);
skipping_inaccuracies_distance, coordinates);
BOOST_ASSERT(is_valid_result(result)); BOOST_ASSERT(is_valid_result(result));
return result; return result;
} }

View File

@ -10,8 +10,8 @@
#include "extractor/restriction_parser.hpp" #include "extractor/restriction_parser.hpp"
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/exception.hpp" #include "util/exception.hpp"
#include "util/lua_util.hpp"
#include "util/log.hpp" #include "util/log.hpp"
#include "util/lua_util.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <osmium/osm.hpp> #include <osmium/osm.hpp>
@ -51,7 +51,7 @@ auto get_value_by_key(T const &object, const char *key) -> decltype(object.get_v
} }
template <class T, class D> template <class T, class D>
const char* get_value_by_key(T const &object, const char *key, D const default_value) const char *get_value_by_key(T const &object, const char *key, D const default_value)
{ {
auto v = get_value_by_key(object, key); auto v = get_value_by_key(object, key);
if (v && *v) if (v && *v)
@ -176,8 +176,13 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
static_cast<void (std::vector<std::string>::*)(const std::string &)>( static_cast<void (std::vector<std::string>::*)(const std::string &)>(
&std::vector<std::string>::push_back)); &std::vector<std::string>::push_back));
context.state.new_usertype<osmium::Location>( context.state.new_usertype<osmium::Location>("Location",
"Location", "lat", &osmium::Location::lat, "lon", &osmium::Location::lon, "valid", &osmium::Location::valid); "lat",
&osmium::Location::lat,
"lon",
&osmium::Location::lon,
"valid",
&osmium::Location::valid);
context.state.new_usertype<osmium::Way>("Way", context.state.new_usertype<osmium::Way>("Way",
"get_value_by_key", "get_value_by_key",
@ -272,12 +277,11 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"lat", "lat",
&latToDouble<ExternalMemoryNode>); &latToDouble<ExternalMemoryNode>);
context.state.new_usertype<util::Coordinate>( context.state.new_usertype<util::Coordinate>("Coordinate",
"Coordinate", "lon",
"lon", sol::property(&lonToDouble<util::Coordinate>),
sol::property(&lonToDouble<util::Coordinate>), "lat",
"lat", sol::property(&latToDouble<util::Coordinate>));
sol::property(&latToDouble<util::Coordinate>));
context.state.new_usertype<RasterDatum>( context.state.new_usertype<RasterDatum>(
"RasterDatum", "datum", &RasterDatum::datum, "invalid_data", &RasterDatum::get_invalid); "RasterDatum", "datum", &RasterDatum::datum, "invalid_data", &RasterDatum::get_invalid);

View File

@ -14,7 +14,8 @@ constexpr double bearing_scale = 360.0 / 256.0;
// discretizes a bearing into distinct units of 1.4 degrees // discretizes a bearing into distinct units of 1.4 degrees
TurnBearing::TurnBearing(const double value) : bearing(value / bearing_scale) TurnBearing::TurnBearing(const double value) : bearing(value / bearing_scale)
{ {
BOOST_ASSERT_MSG(value >= 0 && value < 360.0, "Bearing value needs to be between 0 and 360 (exclusive)"); BOOST_ASSERT_MSG(value >= 0 && value < 360.0,
"Bearing value needs to be between 0 and 360 (exclusive)");
} }
double TurnBearing::Get() const { return bearing * bearing_scale; } double TurnBearing::Get() const { return bearing * bearing_scale; }

View File

@ -17,7 +17,10 @@
namespace namespace
{ {
osrm::util::Coordinate getZeroCoordinate() { return {osrm::util::FloatLongitude{0}, osrm::util::FloatLatitude{0}}; } osrm::util::Coordinate getZeroCoordinate()
{
return {osrm::util::FloatLongitude{0}, osrm::util::FloatLatitude{0}};
}
} }
BOOST_AUTO_TEST_SUITE(limits) BOOST_AUTO_TEST_SUITE(limits)