2016-01-28 10:28:44 -05:00
|
|
|
#ifndef ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
|
|
|
|
#define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
|
|
|
|
|
|
|
|
#include "engine/guidance/route_step.hpp"
|
|
|
|
#include "engine/guidance/step_maneuver.hpp"
|
|
|
|
#include "engine/guidance/leg_geometry.hpp"
|
2016-02-24 04:29:23 -05:00
|
|
|
#include "engine/guidance/guidance_toolkit.hpp"
|
|
|
|
#include "engine/guidance/turn_instruction.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
#include "engine/internal_route_result.hpp"
|
|
|
|
#include "engine/phantom_node.hpp"
|
|
|
|
#include "util/coordinate_calculation.hpp"
|
|
|
|
#include "util/coordinate.hpp"
|
2016-02-24 04:29:23 -05:00
|
|
|
#include "util/bearing.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
#include "extractor/travel_mode.hpp"
|
|
|
|
|
|
|
|
#include <vector>
|
2016-02-25 04:01:16 -05:00
|
|
|
#include <boost/optional.hpp>
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace engine
|
|
|
|
{
|
|
|
|
namespace guidance
|
|
|
|
{
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
// FIXME move implementation to cpp
|
2016-02-24 08:03:51 -05:00
|
|
|
inline StepManeuver stepManeuverFromGeometry(TurnInstruction instruction,
|
2016-01-28 10:28:44 -05:00
|
|
|
const LegGeometry &leg_geometry,
|
2016-02-24 04:29:23 -05:00
|
|
|
const std::size_t segment_index,
|
|
|
|
const unsigned exit)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
|
|
|
auto turn_index = leg_geometry.BackIndex(segment_index);
|
|
|
|
BOOST_ASSERT(turn_index > 0);
|
|
|
|
BOOST_ASSERT(turn_index < leg_geometry.locations.size() - 1);
|
|
|
|
|
|
|
|
// TODO chose a bigger look-a-head to smooth complex geometry
|
|
|
|
const auto pre_turn_coordinate = leg_geometry.locations[turn_index - 1];
|
|
|
|
const auto turn_coordinate = leg_geometry.locations[turn_index];
|
|
|
|
const auto post_turn_coordinate = leg_geometry.locations[turn_index + 1];
|
|
|
|
|
2016-02-22 16:09:50 -05:00
|
|
|
const double pre_turn_bearing =
|
2016-01-28 10:28:44 -05:00
|
|
|
util::coordinate_calculation::bearing(pre_turn_coordinate, turn_coordinate);
|
2016-02-22 16:09:50 -05:00
|
|
|
const double post_turn_bearing =
|
2016-01-28 10:28:44 -05:00
|
|
|
util::coordinate_calculation::bearing(turn_coordinate, post_turn_coordinate);
|
|
|
|
|
2016-02-24 04:29:23 -05:00
|
|
|
return StepManeuver{turn_coordinate, pre_turn_bearing, post_turn_bearing, instruction, exit};
|
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,
|
2016-02-25 04:01:16 -05:00
|
|
|
const bool target_traversed_in_reverse,
|
|
|
|
boost::optional<util::Coordinate> source_location,
|
|
|
|
boost::optional<util::Coordinate> target_location)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-02-26 11:33:18 -05:00
|
|
|
(void) source_location;
|
2016-01-28 10:28:44 -05:00
|
|
|
const auto source_duration =
|
|
|
|
(source_traversed_in_reverse ? source_node.GetReverseWeightPlusOffset()
|
|
|
|
: source_node.GetForwardWeightPlusOffset()) /
|
|
|
|
10.;
|
|
|
|
const auto source_mode = source_traversed_in_reverse ? source_node.backward_travel_mode
|
|
|
|
: source_node.forward_travel_mode;
|
|
|
|
|
|
|
|
const auto target_duration =
|
|
|
|
(target_traversed_in_reverse ? target_node.GetReverseWeightPlusOffset()
|
|
|
|
: target_node.GetForwardWeightPlusOffset()) /
|
|
|
|
10.;
|
|
|
|
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);
|
|
|
|
|
2016-02-25 04:01:16 -05:00
|
|
|
// TODO do computation based on distance and choose better next vertex
|
2016-02-25 08:40:26 -05:00
|
|
|
BOOST_ASSERT(leg_geometry.locations.size() >= 4); // source, phantom, closest positions on way
|
2016-02-25 04:01:16 -05:00
|
|
|
|
2016-01-28 10:28:44 -05:00
|
|
|
auto segment_index = 0;
|
|
|
|
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(
|
|
|
|
TurnInstruction{TurnType::Location, DirectionModifier::UTurn}, leg_geometry,
|
|
|
|
segment_index, INVALID_EXIT_NR);
|
|
|
|
maneuver.instruction.direction_modifier = bearingToDirectionModifier(maneuver.bearing_before);
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-02-24 04:29:23 -05:00
|
|
|
// TODO fix this: it makes no sense
|
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
|
2016-01-28 10:28:44 -05:00
|
|
|
for (const auto &path_point : leg_data)
|
|
|
|
{
|
2016-02-24 04:29:23 -05:00
|
|
|
if (path_point.turn_instruction != TurnInstruction::NO_TURN())
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-02-24 04:29:23 -05:00
|
|
|
const auto name = facade.get_name_for_id(path_point.name_id);
|
2016-01-28 10:28:44 -05:00
|
|
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
2016-02-24 04:29:23 -05:00
|
|
|
steps.push_back(RouteStep{
|
|
|
|
path_point.name_id, name, path_point.duration_until_turn / 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, leg_geometry, segment_index, path_point.exit);
|
2016-01-28 10:28:44 -05:00
|
|
|
segment_index++;
|
|
|
|
}
|
|
|
|
}
|
2016-02-24 04:29:23 -05:00
|
|
|
// TODO remove this hack
|
2016-01-28 10:28:44 -05:00
|
|
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
|
|
|
steps.push_back(RouteStep{target_node.name_id, facade.get_name_for_id(target_node.name_id),
|
|
|
|
target_duration, distance, target_mode, maneuver,
|
|
|
|
leg_geometry.FrontIndex(segment_index),
|
|
|
|
leg_geometry.BackIndex(segment_index) + 1});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//
|
|
|
|
// |-----s source_duration
|
|
|
|
// |-------------t target_duration
|
|
|
|
// x---*---*---*---z compressed edge
|
|
|
|
// |-------| duration
|
2016-02-24 04:29:23 -05:00
|
|
|
StepManeuver maneuver = {source_node.location, 0., 0.,
|
2016-02-26 11:33:18 -05:00
|
|
|
TurnInstruction{TurnType::Location, DirectionModifier::UTurn},
|
2016-02-24 04:29:23 -05:00
|
|
|
INVALID_EXIT_NR};
|
2016-02-26 11:33:18 -05:00
|
|
|
maneuver.instruction.direction_modifier = bearingToDirectionModifier(maneuver.bearing_before);
|
2016-02-24 04:29:23 -05:00
|
|
|
|
2016-02-25 04:01:16 -05:00
|
|
|
steps.push_back(RouteStep{source_node.name_id, facade.get_name_for_id(source_node.name_id),
|
|
|
|
target_duration - source_duration,
|
|
|
|
leg_geometry.segment_distances[segment_index], source_mode,
|
|
|
|
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
|
|
|
|
leg_geometry.BackIndex(segment_index) + 1});
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
2016-02-25 04:01:16 -05:00
|
|
|
const auto final_modifier =
|
|
|
|
target_location ? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
|
|
|
|
*(leg_geometry.locations.end() - 3),
|
|
|
|
*(leg_geometry.locations.end() - 1), target_location.get()))
|
|
|
|
: DirectionModifier::UTurn;
|
2016-01-28 10:28:44 -05:00
|
|
|
// This step has length zero, the only reason we need it is the target location
|
|
|
|
steps.push_back(RouteStep{
|
|
|
|
target_node.name_id, facade.get_name_for_id(target_node.name_id), 0., 0., target_mode,
|
2016-02-24 04:29:23 -05:00
|
|
|
StepManeuver{target_node.location, 0., 0.,
|
2016-02-25 04:01:16 -05:00
|
|
|
TurnInstruction{TurnType::Location, final_modifier}, INVALID_EXIT_NR},
|
2016-01-28 10:28:44 -05:00
|
|
|
leg_geometry.locations.size(), leg_geometry.locations.size()});
|
|
|
|
|
|
|
|
return steps;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace guidance
|
|
|
|
} // namespace engine
|
|
|
|
} // namespace osrm
|
|
|
|
|
|
|
|
#endif // ENGINE_GUIDANCE_SEGMENT_LIST_HPP_
|