242 lines
7.0 KiB
C++
242 lines
7.0 KiB
C++
#ifndef ROUTE_STEP_HPP
|
|
#define ROUTE_STEP_HPP
|
|
|
|
#include "extractor/travel_mode.hpp"
|
|
#include "engine/guidance/step_maneuver.hpp"
|
|
#include "util/coordinate.hpp"
|
|
#include "util/guidance/bearing_class.hpp"
|
|
#include "util/guidance/entry_class.hpp"
|
|
|
|
#include "extractor/turn_lane_types.hpp"
|
|
#include "util/guidance/turn_lanes.hpp"
|
|
|
|
#include <cstddef>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <boost/range/iterator_range.hpp>
|
|
|
|
namespace osrm
|
|
{
|
|
namespace engine
|
|
{
|
|
namespace guidance
|
|
{
|
|
// Given the following turn from a,b to b,c over b:
|
|
// a --> b --> c
|
|
// this struct saves the information of the segment b,c.
|
|
// Notable exceptions are Departure and Arrival steps.
|
|
// Departure: s --> a --> b. Represents the segment s,a with location being s.
|
|
// Arrive: a --> b --> t. The segment (b,t) is already covered by the previous segment.
|
|
|
|
// A representation of intermediate intersections
|
|
struct IntermediateIntersection
|
|
{
|
|
static const constexpr std::size_t NO_INDEX = std::numeric_limits<std::size_t>::max();
|
|
util::Coordinate location;
|
|
std::vector<short> bearings;
|
|
std::vector<bool> entry;
|
|
std::size_t in;
|
|
std::size_t out;
|
|
|
|
// turn lane information
|
|
util::guidance::LaneTuple lanes;
|
|
extractor::TurnLaneDescription lane_description;
|
|
std::vector<std::string> classes;
|
|
};
|
|
|
|
inline IntermediateIntersection getInvalidIntersection()
|
|
{
|
|
return {util::Coordinate{util::FloatLongitude{0.0}, util::FloatLatitude{0.0}},
|
|
{},
|
|
{},
|
|
IntermediateIntersection::NO_INDEX,
|
|
IntermediateIntersection::NO_INDEX,
|
|
util::guidance::LaneTuple(),
|
|
{},
|
|
{}};
|
|
}
|
|
|
|
struct RouteStep
|
|
{
|
|
NodeID from_id;
|
|
unsigned name_id;
|
|
bool is_segregated;
|
|
std::string name;
|
|
std::string ref;
|
|
std::string pronunciation;
|
|
std::string destinations;
|
|
std::string exits;
|
|
std::string rotary_name;
|
|
std::string rotary_pronunciation;
|
|
double duration; // duration in seconds
|
|
double distance; // distance in meters
|
|
double weight; // weight value
|
|
extractor::TravelMode mode;
|
|
StepManeuver maneuver;
|
|
// indices into the locations array stored the LegGeometry
|
|
std::size_t geometry_begin;
|
|
std::size_t geometry_end;
|
|
std::vector<IntermediateIntersection> intersections;
|
|
bool is_left_hand_driving;
|
|
|
|
// remove all information from the route step, marking it as invalid (used to indicate empty
|
|
// steps to be removed).
|
|
void Invalidate();
|
|
|
|
// Elongate by another step in front
|
|
RouteStep &AddInFront(const RouteStep &preceeding_step);
|
|
|
|
// Elongate by another step in back
|
|
RouteStep &ElongateBy(const RouteStep &following_step);
|
|
|
|
/* 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 */
|
|
RouteStep &MergeWith(const RouteStep &by_step);
|
|
|
|
// copy all strings from origin into the step, apart from rotary names
|
|
RouteStep &AdaptStepSignage(const RouteStep &origin);
|
|
|
|
// Lane utilities for the step's turn.
|
|
// A step may have lanes left or right of the turn: think left turn with lanes going straight.
|
|
// Note: Lanes for intersections along the way are available via intersections[n].lanes.
|
|
|
|
bool HasLanesAtTurn() const;
|
|
|
|
LaneID NumLanesInTurn() const;
|
|
LaneID NumLanesInTotal() const;
|
|
|
|
LaneID NumLanesToTheRight() const;
|
|
LaneID NumLanesToTheLeft() const;
|
|
|
|
auto LanesToTheLeft() const;
|
|
auto LanesToTheRight() const;
|
|
};
|
|
|
|
inline void RouteStep::Invalidate()
|
|
{
|
|
name_id = EMPTY_NAMEID;
|
|
name.clear();
|
|
ref.clear();
|
|
pronunciation.clear();
|
|
destinations.clear();
|
|
exits.clear();
|
|
rotary_name.clear();
|
|
rotary_pronunciation.clear();
|
|
duration = 0;
|
|
distance = 0;
|
|
weight = 0;
|
|
mode = extractor::TRAVEL_MODE_INACCESSIBLE;
|
|
maneuver = getInvalidStepManeuver();
|
|
geometry_begin = 0;
|
|
geometry_end = 0;
|
|
intersections.clear();
|
|
intersections.push_back(getInvalidIntersection());
|
|
is_left_hand_driving = false;
|
|
}
|
|
|
|
// 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;
|
|
weight += preceeding_step.weight;
|
|
|
|
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;
|
|
weight += following_step.weight;
|
|
|
|
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;
|
|
exits = origin.exits;
|
|
ref = origin.ref;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline bool RouteStep::HasLanesAtTurn() const { return NumLanesInTotal() != 0; }
|
|
|
|
inline LaneID RouteStep::NumLanesInTurn() const
|
|
{
|
|
return intersections.front().lanes.lanes_in_turn;
|
|
}
|
|
|
|
inline LaneID RouteStep::NumLanesInTotal() const
|
|
{
|
|
return intersections.front().lane_description.size();
|
|
}
|
|
|
|
inline LaneID RouteStep::NumLanesToTheRight() const
|
|
{
|
|
if (!HasLanesAtTurn())
|
|
return 0;
|
|
|
|
return intersections.front().lanes.first_lane_from_the_right;
|
|
}
|
|
|
|
inline LaneID RouteStep::NumLanesToTheLeft() const
|
|
{
|
|
if (!HasLanesAtTurn())
|
|
return 0;
|
|
|
|
return NumLanesInTotal() - (NumLanesInTurn() + NumLanesToTheRight());
|
|
}
|
|
|
|
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
|