2016-01-28 10:28:44 -05:00
|
|
|
#ifndef ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
|
|
|
|
#define ENGINE_GUIDANCE_ASSEMBLE_STEPS_HPP_
|
|
|
|
|
2016-05-27 15:05:04 -04:00
|
|
|
#include "extractor/guidance/turn_instruction.hpp"
|
2016-06-21 04:41:08 -04:00
|
|
|
#include "extractor/guidance/turn_lane_types.hpp"
|
2016-07-21 08:34:32 -04:00
|
|
|
#include "extractor/travel_mode.hpp"
|
2016-06-14 06:16:42 -04:00
|
|
|
#include "engine/datafacade/datafacade_base.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"
|
|
|
|
#include "engine/internal_route_result.hpp"
|
|
|
|
#include "engine/phantom_node.hpp"
|
2016-03-23 08:04:23 -04:00
|
|
|
#include "util/bearing.hpp"
|
|
|
|
#include "util/coordinate.hpp"
|
|
|
|
#include "util/coordinate_calculation.hpp"
|
2016-04-26 07:27:40 -04:00
|
|
|
#include "util/guidance/entry_class.hpp"
|
2016-06-15 08:38:24 -04:00
|
|
|
#include "util/guidance/turn_lanes.hpp"
|
2016-04-26 07:27:40 -04:00
|
|
|
#include "util/typedefs.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-02-25 04:01:16 -05:00
|
|
|
#include <boost/optional.hpp>
|
2016-04-21 07:59:03 -04:00
|
|
|
#include <cstddef>
|
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
|
|
|
|
{
|
2017-08-28 12:03:51 -04:00
|
|
|
std::pair<short, short> getDepartBearings(const LegGeometry &leg_geometry,
|
|
|
|
const PhantomNode &source_node,
|
|
|
|
const bool traversed_in_reverse);
|
|
|
|
std::pair<short, short> getArriveBearings(const LegGeometry &leg_geometry,
|
|
|
|
const PhantomNode &target_node,
|
|
|
|
const bool traversed_in_reverse);
|
2016-03-03 09:34:13 -05:00
|
|
|
} // ns detail
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-06-14 06:16:42 -04:00
|
|
|
inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &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
|
|
|
{
|
2017-01-17 03:24:52 -05:00
|
|
|
const double weight_multiplier = facade.GetWeightMultiplier();
|
2016-05-12 12:50:10 -04:00
|
|
|
|
|
|
|
const double constexpr ZERO_DURATION = 0., ZERO_DISTANCE = 0., ZERO_WEIGHT = 0;
|
2016-03-23 08:04:23 -04:00
|
|
|
const constexpr char *NO_ROTARY_NAME = "";
|
2016-05-12 12:50:10 -04:00
|
|
|
const EdgeWeight source_weight =
|
2016-03-18 11:14:48 -04:00
|
|
|
source_traversed_in_reverse ? source_node.reverse_weight : source_node.forward_weight;
|
2016-05-12 12:50:10 -04:00
|
|
|
const EdgeWeight source_duration =
|
|
|
|
source_traversed_in_reverse ? source_node.reverse_duration : source_node.forward_duration;
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto source_node_id = source_traversed_in_reverse ? source_node.reverse_segment_id.id
|
|
|
|
: source_node.forward_segment_id.id;
|
|
|
|
const auto source_name_id = facade.GetNameIndex(source_node_id);
|
2017-10-19 09:56:47 -04:00
|
|
|
bool is_segregated = facade.IsSegregated(source_node_id);
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto source_mode = facade.GetTravelMode(source_node_id);
|
2017-06-27 18:01:05 -04:00
|
|
|
auto source_classes = facade.GetClasses(facade.GetClassData(source_node_id));
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-03-17 15:39:19 -04:00
|
|
|
const EdgeWeight target_duration =
|
2016-05-12 12:50:10 -04:00
|
|
|
target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration;
|
|
|
|
const EdgeWeight target_weight =
|
2016-03-18 11:14:48 -04:00
|
|
|
target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight;
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id
|
|
|
|
: target_node.forward_segment_id.id;
|
|
|
|
const auto target_name_id = facade.GetNameIndex(target_node_id);
|
|
|
|
const auto target_mode = facade.GetTravelMode(target_node_id);
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
const auto number_of_segments = leg_geometry.GetNumberOfSegments();
|
|
|
|
|
|
|
|
std::vector<RouteStep> steps;
|
|
|
|
steps.reserve(number_of_segments);
|
|
|
|
|
2016-02-29 10:24:42 -05:00
|
|
|
std::size_t segment_index = 0;
|
2016-03-08 10:46:01 -05:00
|
|
|
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
|
|
|
|
|
2017-08-28 12:03:51 -04:00
|
|
|
auto bearings =
|
|
|
|
detail::getDepartBearings(leg_geometry, source_node, source_traversed_in_reverse);
|
2016-02-25 04:01:16 -05:00
|
|
|
|
2016-05-27 15:05:04 -04:00
|
|
|
StepManeuver maneuver{source_node.location,
|
|
|
|
bearings.first,
|
|
|
|
bearings.second,
|
|
|
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
|
|
|
WaypointType::Depart,
|
2016-07-21 08:34:32 -04:00
|
|
|
0};
|
|
|
|
|
2016-12-20 08:57:08 -05:00
|
|
|
IntermediateIntersection intersection{source_node.location,
|
|
|
|
std::vector<short>({bearings.second}),
|
|
|
|
std::vector<bool>({true}),
|
|
|
|
IntermediateIntersection::NO_INDEX,
|
|
|
|
0,
|
|
|
|
util::guidance::LaneTuple(),
|
2017-07-13 19:19:20 -04:00
|
|
|
{},
|
|
|
|
source_classes};
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-05-18 11:53:05 -04:00
|
|
|
if (leg_data.size() > 0)
|
|
|
|
{
|
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-05-12 12:50:10 -04:00
|
|
|
EdgeWeight segment_duration = 0;
|
|
|
|
EdgeWeight segment_weight = 0;
|
2016-04-21 07:59:03 -04:00
|
|
|
|
|
|
|
// some name changes are not announced in our processing. For these, we have to keep the
|
|
|
|
// first name on the segment
|
2017-05-11 03:13:59 -04:00
|
|
|
auto step_name_id = source_name_id;
|
2016-04-21 07:59:03 -04:00
|
|
|
for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-04-21 07:59:03 -04:00
|
|
|
const auto &path_point = leg_data[leg_data_index];
|
2016-03-17 15:39:19 -04:00
|
|
|
segment_duration += path_point.duration_until_turn;
|
2016-05-12 12:50:10 -04:00
|
|
|
segment_weight += path_point.weight_until_turn;
|
2016-03-17 15:39:19 -04:00
|
|
|
|
2016-03-22 08:40:13 -04:00
|
|
|
// all changes to this check have to be matched with assemble_geometry
|
2016-03-21 13:07:28 -04:00
|
|
|
if (path_point.turn_instruction.type != extractor::guidance::TurnType::NoTurn)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-05-12 12:50:10 -04:00
|
|
|
BOOST_ASSERT(segment_weight >= 0);
|
2016-04-21 07:59:03 -04:00
|
|
|
const auto name = facade.GetNameForID(step_name_id);
|
2016-09-05 09:01:51 -04:00
|
|
|
const auto ref = facade.GetRefForID(step_name_id);
|
2016-05-25 21:35:38 -04:00
|
|
|
const auto pronunciation = facade.GetPronunciationForID(step_name_id);
|
2016-05-26 18:47:46 -04:00
|
|
|
const auto destinations = facade.GetDestinationsForID(step_name_id);
|
2017-06-29 16:12:25 -04:00
|
|
|
const auto exits = facade.GetExitsForID(step_name_id);
|
2016-01-28 10:28:44 -05:00
|
|
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
2017-07-13 19:19:20 -04:00
|
|
|
// intersections contain the classes of exiting road
|
|
|
|
intersection.classes = facade.GetClasses(path_point.classes);
|
2016-05-18 11:53:05 -04:00
|
|
|
|
2016-05-25 09:24:11 -04:00
|
|
|
steps.push_back(RouteStep{step_name_id,
|
2017-10-19 09:56:47 -04:00
|
|
|
is_segregated,
|
2016-12-15 12:27:09 -05:00
|
|
|
name.to_string(),
|
|
|
|
ref.to_string(),
|
|
|
|
pronunciation.to_string(),
|
|
|
|
destinations.to_string(),
|
2017-06-29 16:12:25 -04:00
|
|
|
exits.to_string(),
|
2016-05-25 09:24:11 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-09-07 09:51:14 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-05-12 12:50:10 -04:00
|
|
|
segment_duration / 10.,
|
2016-05-25 09:24:11 -04:00
|
|
|
distance,
|
2016-05-12 12:50:10 -04:00
|
|
|
segment_weight / weight_multiplier,
|
2016-05-25 09:24:11 -04:00
|
|
|
path_point.travel_mode,
|
|
|
|
maneuver,
|
|
|
|
leg_geometry.FrontIndex(segment_index),
|
|
|
|
leg_geometry.BackIndex(segment_index) + 1,
|
2017-10-31 23:51:11 -04:00
|
|
|
{intersection},
|
|
|
|
path_point.is_left_hand_driving});
|
2016-05-25 09:24:11 -04:00
|
|
|
|
2016-05-10 02:37:45 -04:00
|
|
|
if (leg_data_index + 1 < leg_data.size())
|
|
|
|
{
|
2016-04-21 07:59:03 -04:00
|
|
|
step_name_id = leg_data[leg_data_index + 1].name_id;
|
2017-10-19 09:56:47 -04:00
|
|
|
is_segregated = leg_data[leg_data_index + 1].is_segregated;
|
2016-05-10 02:37:45 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-11 03:13:59 -04:00
|
|
|
step_name_id = facade.GetNameIndex(target_node_id);
|
2017-10-19 09:56:47 -04:00
|
|
|
is_segregated = facade.IsSegregated(target_node_id);
|
2016-04-21 07:59:03 -04:00
|
|
|
}
|
2016-05-18 11:53:05 -04:00
|
|
|
|
2016-08-17 03:49:19 -04:00
|
|
|
// extract bearings
|
|
|
|
bearings = std::make_pair<std::uint16_t, std::uint16_t>(
|
|
|
|
path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get());
|
2017-06-19 09:27:46 -04:00
|
|
|
const auto bearing_class = facade.GetBearingClass(path_point.turn_via_node);
|
2016-08-17 03:49:19 -04:00
|
|
|
auto bearing_data = bearing_class.getAvailableBearings();
|
|
|
|
intersection.in = bearing_class.findMatchingBearing(bearings.first);
|
2016-05-18 11:53:05 -04:00
|
|
|
intersection.out = bearing_class.findMatchingBearing(bearings.second);
|
|
|
|
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
|
|
|
intersection.bearings.clear();
|
2016-12-13 05:48:21 -05:00
|
|
|
intersection.bearings.reserve(bearing_data.size());
|
2016-07-21 08:34:32 -04:00
|
|
|
intersection.lanes = path_point.lane_data.first;
|
|
|
|
intersection.lane_description =
|
|
|
|
path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
|
|
|
|
? facade.GetTurnDescription(path_point.lane_data.second)
|
|
|
|
: extractor::guidance::TurnLaneDescription();
|
2017-01-04 11:09:44 -05:00
|
|
|
|
|
|
|
// Lanes in turn are bound by total number of lanes at the location
|
|
|
|
BOOST_ASSERT(intersection.lanes.lanes_in_turn <=
|
|
|
|
intersection.lane_description.size());
|
|
|
|
// No lanes at location and no turn lane or lanes at location and lanes in turn
|
|
|
|
BOOST_ASSERT((intersection.lane_description.empty() &&
|
|
|
|
intersection.lanes.lanes_in_turn == 0) ||
|
|
|
|
(!intersection.lane_description.empty() &&
|
|
|
|
intersection.lanes.lanes_in_turn != 0));
|
|
|
|
|
2016-12-13 05:48:21 -05:00
|
|
|
std::copy(bearing_data.begin(),
|
|
|
|
bearing_data.end(),
|
2016-05-18 11:53:05 -04:00
|
|
|
std::back_inserter(intersection.bearings));
|
|
|
|
intersection.entry.clear();
|
|
|
|
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
|
|
|
|
{
|
2017-06-19 09:27:46 -04:00
|
|
|
intersection.entry.push_back(path_point.entry_class.allowsEntry(idx));
|
2016-05-18 11:53:05 -04:00
|
|
|
}
|
2016-08-17 03:49:19 -04:00
|
|
|
std::int16_t bearing_in_driving_direction =
|
2016-12-06 07:22:51 -05:00
|
|
|
util::bearing::reverse(std::round(bearings.first));
|
2016-05-27 15:05:04 -04:00
|
|
|
maneuver = {intersection.location,
|
2016-08-17 03:49:19 -04:00
|
|
|
bearing_in_driving_direction,
|
2016-05-27 15:05:04 -04:00
|
|
|
bearings.second,
|
|
|
|
path_point.turn_instruction,
|
|
|
|
WaypointType::None,
|
2016-07-21 08:34:32 -04:00
|
|
|
0};
|
2016-01-28 10:28:44 -05:00
|
|
|
segment_index++;
|
2016-03-17 15:39:19 -04:00
|
|
|
segment_duration = 0;
|
2016-05-12 12:50:10 -04:00
|
|
|
segment_weight = 0;
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
2016-05-12 12:50:10 -04:00
|
|
|
const EdgeWeight duration = segment_duration + target_duration;
|
|
|
|
const EdgeWeight weight = segment_weight + target_weight;
|
2017-07-13 19:19:20 -04:00
|
|
|
// intersections contain the classes of exiting road
|
|
|
|
intersection.classes = facade.GetClasses(facade.GetClassData(target_node_id));
|
2016-03-17 15:39:19 -04:00
|
|
|
BOOST_ASSERT(duration >= 0);
|
2016-05-25 09:24:11 -04:00
|
|
|
steps.push_back(RouteStep{step_name_id,
|
2017-10-19 09:56:47 -04:00
|
|
|
is_segregated,
|
2016-12-15 12:27:09 -05:00
|
|
|
facade.GetNameForID(step_name_id).to_string(),
|
|
|
|
facade.GetRefForID(step_name_id).to_string(),
|
|
|
|
facade.GetPronunciationForID(step_name_id).to_string(),
|
|
|
|
facade.GetDestinationsForID(step_name_id).to_string(),
|
2017-06-29 16:12:25 -04:00
|
|
|
facade.GetExitsForID(step_name_id).to_string(),
|
2016-05-25 09:24:11 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-09-07 09:51:14 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-05-25 09:24:11 -04:00
|
|
|
duration / 10.,
|
|
|
|
distance,
|
2016-05-12 12:50:10 -04:00
|
|
|
weight / weight_multiplier,
|
2016-05-25 09:24:11 -04:00
|
|
|
target_mode,
|
|
|
|
maneuver,
|
|
|
|
leg_geometry.FrontIndex(segment_index),
|
|
|
|
leg_geometry.BackIndex(segment_index) + 1,
|
2017-10-31 23:51:11 -04:00
|
|
|
{intersection},
|
|
|
|
facade.IsLeftHandDriving(target_node_id)});
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
2016-03-17 15:39:19 -04:00
|
|
|
// In this case the source + target are on the same edge segment
|
2016-01-28 10:28:44 -05:00
|
|
|
else
|
|
|
|
{
|
2016-03-17 15:39:19 -04:00
|
|
|
BOOST_ASSERT(source_node.fwd_segment_position == target_node.fwd_segment_position);
|
2017-03-11 08:46:22 -05:00
|
|
|
BOOST_ASSERT(source_traversed_in_reverse == target_traversed_in_reverse);
|
|
|
|
|
|
|
|
// The difference (target-source) should handle
|
|
|
|
// all variants for similar directions u-v and s-t (and opposite)
|
|
|
|
// s(t) t(s) source_traversed_in_reverse = target_traversed_in_reverse = false
|
2016-03-17 15:39:19 -04:00
|
|
|
// u-------------v
|
2017-03-11 08:46:22 -05:00
|
|
|
// |---| source_weight
|
|
|
|
// |---------| target_weight
|
2016-03-17 15:39:19 -04:00
|
|
|
|
2017-03-11 08:46:22 -05:00
|
|
|
// s(t) t(s) source_traversed_in_reverse = target_traversed_in_reverse = true
|
|
|
|
// u-------------v
|
|
|
|
// | |---------| source_weight
|
|
|
|
// | |---| target_weight
|
2017-05-03 17:40:09 -04:00
|
|
|
BOOST_ASSERT(target_weight >= source_weight);
|
2016-05-12 12:50:10 -04:00
|
|
|
const EdgeWeight weight = target_weight - source_weight;
|
2017-05-02 16:13:20 -04:00
|
|
|
|
|
|
|
// use rectified linear unit function to avoid negative duration values
|
|
|
|
// due to flooring errors in phantom snapping
|
2017-05-03 17:40:09 -04:00
|
|
|
BOOST_ASSERT(target_duration >= source_duration || weight == 0);
|
2017-05-02 16:13:20 -04:00
|
|
|
const EdgeWeight duration = std::max(0, target_duration - source_duration);
|
2016-02-24 04:29:23 -05:00
|
|
|
|
2017-05-11 03:13:59 -04:00
|
|
|
steps.push_back(RouteStep{source_name_id,
|
2017-10-19 09:56:47 -04:00
|
|
|
is_segregated,
|
2017-05-11 03:13:59 -04:00
|
|
|
facade.GetNameForID(source_name_id).to_string(),
|
|
|
|
facade.GetRefForID(source_name_id).to_string(),
|
|
|
|
facade.GetPronunciationForID(source_name_id).to_string(),
|
|
|
|
facade.GetDestinationsForID(source_name_id).to_string(),
|
2017-06-29 16:12:25 -04:00
|
|
|
facade.GetExitsForID(source_name_id).to_string(),
|
2016-05-25 09:24:11 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-09-07 09:51:14 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-05-25 09:24:11 -04:00
|
|
|
duration / 10.,
|
|
|
|
leg_geometry.segment_distances[segment_index],
|
2016-05-12 12:50:10 -04:00
|
|
|
weight / weight_multiplier,
|
2016-05-25 09:24:11 -04:00
|
|
|
source_mode,
|
|
|
|
std::move(maneuver),
|
|
|
|
leg_geometry.FrontIndex(segment_index),
|
|
|
|
leg_geometry.BackIndex(segment_index) + 1,
|
2017-10-31 23:51:11 -04:00
|
|
|
{intersection},
|
|
|
|
facade.IsLeftHandDriving(source_node_id)});
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
2017-08-28 12:03:51 -04:00
|
|
|
bearings = detail::getArriveBearings(leg_geometry, target_node, target_traversed_in_reverse);
|
2016-07-21 08:34:32 -04:00
|
|
|
|
2016-12-06 07:22:51 -05:00
|
|
|
intersection = {
|
|
|
|
target_node.location,
|
|
|
|
std::vector<short>({static_cast<short>(util::bearing::reverse(bearings.first))}),
|
|
|
|
std::vector<bool>({true}),
|
|
|
|
0,
|
|
|
|
IntermediateIntersection::NO_INDEX,
|
|
|
|
util::guidance::LaneTuple(),
|
2017-07-13 19:19:20 -04:00
|
|
|
{},
|
2016-12-06 07:22:51 -05:00
|
|
|
{}};
|
2016-04-06 10:47:16 -04:00
|
|
|
|
2016-11-08 06:52:15 -05:00
|
|
|
// This step has length zero, the only reason we need it is the target location
|
|
|
|
maneuver = {intersection.location,
|
|
|
|
bearings.first,
|
|
|
|
bearings.second,
|
|
|
|
extractor::guidance::TurnInstruction::NO_TURN(),
|
|
|
|
WaypointType::Arrive,
|
|
|
|
0};
|
|
|
|
|
2016-04-06 10:47:16 -04:00
|
|
|
BOOST_ASSERT(!leg_geometry.locations.empty());
|
2017-05-11 03:13:59 -04:00
|
|
|
steps.push_back(RouteStep{target_name_id,
|
2017-10-19 09:56:47 -04:00
|
|
|
facade.IsSegregated(target_node_id),
|
2017-05-11 03:13:59 -04:00
|
|
|
facade.GetNameForID(target_name_id).to_string(),
|
|
|
|
facade.GetRefForID(target_name_id).to_string(),
|
|
|
|
facade.GetPronunciationForID(target_name_id).to_string(),
|
|
|
|
facade.GetDestinationsForID(target_name_id).to_string(),
|
2017-06-29 16:12:25 -04:00
|
|
|
facade.GetExitsForID(target_name_id).to_string(),
|
2016-05-25 09:24:11 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-09-07 09:51:14 -04:00
|
|
|
NO_ROTARY_NAME,
|
2016-05-25 09:24:11 -04:00
|
|
|
ZERO_DURATION,
|
|
|
|
ZERO_DISTANCE,
|
2016-05-12 12:50:10 -04:00
|
|
|
ZERO_WEIGHT,
|
2016-05-25 09:24:11 -04:00
|
|
|
target_mode,
|
|
|
|
std::move(maneuver),
|
|
|
|
leg_geometry.locations.size() - 1,
|
2016-05-10 02:37:45 -04:00
|
|
|
leg_geometry.locations.size(),
|
2017-10-31 23:51:11 -04:00
|
|
|
{intersection},
|
|
|
|
facade.IsLeftHandDriving(source_node_id)});
|
2016-05-18 11:53:05 -04:00
|
|
|
|
|
|
|
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
|
|
|
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
|
|
|
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
|
|
|
BOOST_ASSERT(steps.front().maneuver.waypoint_type == WaypointType::Depart);
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-05-18 11:53:05 -04:00
|
|
|
BOOST_ASSERT(steps.back().intersections.size() == 1);
|
|
|
|
BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1);
|
|
|
|
BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1);
|
|
|
|
BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive);
|
2016-07-21 08:34:32 -04:00
|
|
|
BOOST_ASSERT(steps.back().intersections.front().lanes.lanes_in_turn == 0);
|
2016-07-26 09:00:58 -04:00
|
|
|
BOOST_ASSERT(steps.back().intersections.front().lanes.first_lane_from_the_right ==
|
|
|
|
INVALID_LANEID);
|
2016-07-21 08:34:32 -04:00
|
|
|
BOOST_ASSERT(steps.back().intersections.front().lane_description.empty());
|
2016-12-21 03:33:15 -05:00
|
|
|
// depart and arrive need to be trivial
|
|
|
|
BOOST_ASSERT(steps.front().maneuver.exit == 0 && steps.back().maneuver.exit == 0);
|
2016-01-28 10:28:44 -05:00
|
|
|
return steps;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace guidance
|
|
|
|
} // namespace engine
|
|
|
|
} // namespace osrm
|
|
|
|
|
|
|
|
#endif // ENGINE_GUIDANCE_SEGMENT_LIST_HPP_
|