osrm-backend/include/engine/guidance/toolkit.hpp
Moritz Kobitzsch cd03877c90 link ConnectedRoad and TurnOperation via class hierarchy
and empower intersection by adding basic functionality to pod type
refactor extractor/toolkit into intersection
2016-11-03 13:42:29 +01:00

109 lines
3.5 KiB
C++

#ifndef OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#define OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/bearing.hpp"
#include "util/guidance/toolkit.hpp"
#include <algorithm>
#include <iterator>
#include <utility>
namespace osrm
{
namespace engine
{
namespace guidance
{
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
using util::guidance::staysOnRoundabout;
// Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::NoTurn ||
instruction.type == extractor::guidance::TurnType::Suppressed ||
instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(const double bearing)
{
if (bearing < 135)
{
return extractor::guidance::DirectionModifier::Right;
}
if (bearing <= 225)
{
return extractor::guidance::DirectionModifier::Straight;
}
return extractor::guidance::DirectionModifier::Left;
}
// Runs fn on RouteStep sub-ranges determined to be roundabouts.
// The function fn is getting called with a roundabout range as in: [enter, .., leave].
//
// The following situations are taken care for (i.e. we discard them):
// - partial roundabout: enter without exit or exit without enter
// - data issues: no roundabout, exit before enter
template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, Iter last, Fn fn)
{
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
break;
(void)fn(std::make_pair(enter, leave));
// Skip to first step after the currently handled enter / leave pair
first = std::next(leave);
}
return fn;
}
LaneID inline numLanesToTheRight(const engine::guidance::RouteStep &step)
{
return step.intersections.front().lanes.first_lane_from_the_right;
}
LaneID inline numLanesToTheLeft(const engine::guidance::RouteStep &step)
{
LaneID const total = step.intersections.front().lane_description.size();
return total - (step.intersections.front().lanes.lanes_in_turn +
step.intersections.front().lanes.first_lane_from_the_right);
}
auto inline lanesToTheLeft(const engine::guidance::RouteStep &step)
{
const auto &description = step.intersections.front().lane_description;
LaneID num_lanes_left = numLanesToTheLeft(step);
return boost::make_iterator_range(description.begin(), description.begin() + num_lanes_left);
}
auto inline lanesToTheRight(const engine::guidance::RouteStep &step)
{
const auto &description = step.intersections.front().lane_description;
LaneID num_lanes_right = numLanesToTheRight(step);
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_ */