osrm-backend/include/engine/guidance/assemble_steps.hpp

144 lines
6.5 KiB
C++
Raw Normal View History

2016-01-28 10:28:44 -05:00
#ifndef ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
#define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
2016-03-23 08:04:23 -04:00
#include "engine/guidance/leg_geometry.hpp"
2016-01-28 10:28:44 -05:00
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/step_maneuver.hpp"
2016-03-01 16:30:31 -05:00
#include "engine/guidance/toolkit.hpp"
2016-01-28 10:28:44 -05:00
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
2016-03-23 08:04:23 -04:00
#include "extractor/guidance/turn_instruction.hpp"
2016-01-28 10:28:44 -05:00
#include "extractor/travel_mode.hpp"
2016-03-23 08:04:23 -04:00
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
2016-01-28 10:28:44 -05:00
2016-02-25 04:01:16 -05:00
#include <boost/optional.hpp>
2016-03-23 08:04:23 -04:00
#include <vector>
2016-01-28 10:28:44 -05:00
namespace osrm
{
namespace engine
{
namespace guidance
{
namespace detail
{
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const LegGeometry &leg_geometry,
const std::size_t segment_index);
2016-03-22 08:40:13 -04:00
StepManeuver stepManeuverFromGeometry(extractor::guidance::TurnInstruction instruction,
const WaypointType waypoint_type,
const LegGeometry &leg_geometry);
} // ns detail
2016-01-28 10:28:44 -05:00
template <typename DataFacadeT>
std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
const std::vector<PathData> &leg_data,
const LegGeometry &leg_geometry,
const PhantomNode &source_node,
const PhantomNode &target_node,
const bool source_traversed_in_reverse,
const bool target_traversed_in_reverse)
2016-01-28 10:28:44 -05:00
{
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0.;
2016-03-23 08:04:23 -04:00
const constexpr char *NO_ROTARY_NAME = "";
const EdgeWeight source_duration =
2016-03-18 11:14:48 -04:00
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
2016-01-28 10:28:44 -05:00
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
: source_node.forward_travel_mode;
const EdgeWeight target_duration =
2016-03-18 11:14:48 -04:00
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
2016-01-28 10:28:44 -05:00
const auto target_mode = target_traversed_in_reverse ? target_node.backward_travel_mode
: target_node.forward_travel_mode;
const auto number_of_segments = leg_geometry.GetNumberOfSegments();
std::vector<RouteStep> steps;
steps.reserve(number_of_segments);
std::size_t segment_index = 0;
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
2016-01-28 10:28:44 -05:00
if (leg_data.size() > 0)
{
2016-02-25 04:01:16 -05:00
2016-02-26 11:33:18 -05:00
StepManeuver maneuver = detail::stepManeuverFromGeometry(
2016-03-29 07:45:48 -04:00
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
2016-03-22 08:40:13 -04:00
maneuver.location = source_node.location;
2016-01-28 10:28:44 -05:00
// PathData saves the information we need of the segment _before_ the turn,
// but a RouteStep is with regard to the segment after the turn.
// We need to skip the first segment because it is already covered by the
2016-02-24 04:29:23 -05:00
// initial start of a route
int segment_duration = 0;
2016-01-28 10:28:44 -05:00
for (const auto &path_point : leg_data)
{
segment_duration += path_point.duration_until_turn;
2016-03-22 08:40:13 -04:00
// all changes to this check have to be matched with assemble_geometry
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
2016-01-28 10:28:44 -05:00
{
BOOST_ASSERT(segment_duration >= 0);
2016-03-18 14:21:13 -04:00
const auto name = facade.GetNameForID(path_point.name_id);
2016-01-28 10:28:44 -05:00
const auto distance = leg_geometry.segment_distances[segment_index];
2016-03-23 08:04:23 -04:00
steps.push_back(RouteStep{path_point.name_id, name, NO_ROTARY_NAME,
segment_duration / 10.0, distance, path_point.travel_mode,
maneuver, leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
maneuver = detail::stepManeuverFromGeometry(path_point.turn_instruction,
2016-03-22 08:40:13 -04:00
leg_geometry, segment_index);
2016-01-28 10:28:44 -05:00
segment_index++;
segment_duration = 0;
2016-01-28 10:28:44 -05:00
}
}
const auto distance = leg_geometry.segment_distances[segment_index];
const int duration = segment_duration + target_duration;
BOOST_ASSERT(duration >= 0);
2016-03-23 08:04:23 -04:00
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
NO_ROTARY_NAME, duration / 10., distance, target_mode, maneuver,
2016-01-28 10:28:44 -05:00
leg_geometry.FrontIndex(segment_index),
leg_geometry.BackIndex(segment_index) + 1});
}
// In this case the source + target are on the same edge segment
2016-01-28 10:28:44 -05:00
else
{
BOOST_ASSERT(source_node.fwd_segment_position == target_node.fwd_segment_position);
// s t
// u-------------v
// |---| source_duration
// |---------| target_duration
2016-03-22 08:40:13 -04:00
StepManeuver maneuver = detail::stepManeuverFromGeometry(
2016-03-29 07:45:48 -04:00
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
int duration = target_duration - source_duration;
BOOST_ASSERT(duration >= 0);
2016-02-24 04:29:23 -05:00
2016-03-23 08:04:23 -04:00
steps.push_back(RouteStep{source_node.name_id, facade.GetNameForID(source_node.name_id),
NO_ROTARY_NAME, duration / 10.,
leg_geometry.segment_distances[segment_index], source_mode,
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
2016-02-25 04:01:16 -05:00
leg_geometry.BackIndex(segment_index) + 1});
2016-01-28 10:28:44 -05:00
}
BOOST_ASSERT(segment_index == number_of_segments - 1);
// This step has length zero, the only reason we need it is the target location
2016-03-22 08:40:13 -04:00
auto final_maneuver = detail::stepManeuverFromGeometry(
2016-03-29 07:45:48 -04:00
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, leg_geometry);
2016-03-23 08:04:23 -04:00
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode,
final_maneuver, leg_geometry.locations.size(),
2016-03-22 08:40:13 -04:00
leg_geometry.locations.size()});
2016-01-28 10:28:44 -05:00
return steps;
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif // ENGINE_GUIDANCE_SEGMENT_LIST_HPP_