link ConnectedRoad and TurnOperation via class hierarchy
and empower intersection by adding basic functionality to pod type refactor extractor/toolkit into intersection
This commit is contained in:
@@ -1,6 +1,13 @@
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <boost/range/algorithm/find_if.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
@@ -9,44 +16,101 @@ namespace guidance
|
||||
{
|
||||
|
||||
ConnectedRoad::ConnectedRoad(const TurnOperation turn, const bool entry_allowed)
|
||||
: entry_allowed(entry_allowed), turn(turn)
|
||||
: TurnOperation(turn), entry_allowed(entry_allowed)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConnectedRoad::compareByAngle(const ConnectedRoad &other) const { return angle < other.angle; }
|
||||
|
||||
void ConnectedRoad::mirror()
|
||||
{
|
||||
const constexpr DirectionModifier::Enum mirrored_modifiers[] = {DirectionModifier::UTurn,
|
||||
DirectionModifier::SharpLeft,
|
||||
DirectionModifier::Left,
|
||||
DirectionModifier::SlightLeft,
|
||||
DirectionModifier::Straight,
|
||||
DirectionModifier::SlightRight,
|
||||
DirectionModifier::Right,
|
||||
DirectionModifier::SharpRight};
|
||||
|
||||
static_assert(sizeof(mirrored_modifiers) / sizeof(DirectionModifier::Enum) ==
|
||||
DirectionModifier::MaxDirectionModifier,
|
||||
"The list of mirrored modifiers needs to match the available modifiers in size.");
|
||||
|
||||
if (angularDeviation(angle, 0) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
angle = 360 - angle;
|
||||
instruction.direction_modifier = mirrored_modifiers[instruction.direction_modifier];
|
||||
}
|
||||
}
|
||||
|
||||
ConnectedRoad ConnectedRoad::getMirroredCopy() const
|
||||
{
|
||||
ConnectedRoad copy(*this);
|
||||
copy.mirror();
|
||||
return copy;
|
||||
}
|
||||
|
||||
std::string toString(const ConnectedRoad &road)
|
||||
{
|
||||
std::string result = "[connection] ";
|
||||
result += std::to_string(road.turn.eid);
|
||||
result += std::to_string(road.eid);
|
||||
result += " allows entry: ";
|
||||
result += std::to_string(road.entry_allowed);
|
||||
result += " angle: ";
|
||||
result += std::to_string(road.turn.angle);
|
||||
result += std::to_string(road.angle);
|
||||
result += " bearing: ";
|
||||
result += std::to_string(road.turn.bearing);
|
||||
result += std::to_string(road.bearing);
|
||||
result += " instruction: ";
|
||||
result += std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) +
|
||||
" " + std::to_string(static_cast<std::int32_t>(road.turn.lane_data_id));
|
||||
result += std::to_string(static_cast<std::int32_t>(road.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.instruction.direction_modifier)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.lane_data_id));
|
||||
return result;
|
||||
}
|
||||
|
||||
Intersection::iterator findClosestTurn(Intersection &intersection, const double angle)
|
||||
Intersection::Base::iterator Intersection::findClosestTurn(double angle)
|
||||
{
|
||||
return std::min_element(intersection.begin(),
|
||||
intersection.end(),
|
||||
[angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return angularDeviation(lhs.turn.angle, angle) <
|
||||
angularDeviation(rhs.turn.angle, angle);
|
||||
});
|
||||
// use the const operator to avoid code duplication
|
||||
return begin() +
|
||||
std::distance(cbegin(), static_cast<const Intersection *>(this)->findClosestTurn(angle));
|
||||
}
|
||||
Intersection::const_iterator findClosestTurn(const Intersection &intersection, const double angle)
|
||||
|
||||
Intersection::Base::const_iterator Intersection::findClosestTurn(double angle) const
|
||||
{
|
||||
return std::min_element(intersection.cbegin(),
|
||||
intersection.cend(),
|
||||
[angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return angularDeviation(lhs.turn.angle, angle) <
|
||||
angularDeviation(rhs.turn.angle, angle);
|
||||
});
|
||||
return std::min_element(
|
||||
begin(), end(), [angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return util::guidance::angularDeviation(lhs.angle, angle) <
|
||||
util::guidance::angularDeviation(rhs.angle, angle);
|
||||
});
|
||||
}
|
||||
|
||||
bool Intersection::valid() const
|
||||
{
|
||||
return !empty() &&
|
||||
std::is_sorted(begin(), end(), std::mem_fn(&ConnectedRoad::compareByAngle)) &&
|
||||
operator[](0).angle < std::numeric_limits<double>::epsilon();
|
||||
}
|
||||
|
||||
std::uint8_t Intersection::getHighestConnectedLaneCount(
|
||||
const util::NodeBasedDynamicGraph &node_based_graph) const
|
||||
{
|
||||
BOOST_ASSERT(valid()); // non empty()
|
||||
std::vector<ConnectedRoad> test;
|
||||
const auto to_lane_count = [&](const ConnectedRoad &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
|
||||
};
|
||||
|
||||
// boost::range::transformed sadly does not work with lamdas since they are not copy
|
||||
// constructable. We need to work around this :(
|
||||
std::uint8_t max_lanes = 0;
|
||||
const auto extract_maximal_value = [&max_lanes](std::uint8_t value) {
|
||||
max_lanes = std::max(max_lanes, value);
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto view = test | boost::adaptors::transformed(to_lane_count);
|
||||
boost::range::find_if(view, extract_maximal_value);
|
||||
return max_lanes;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
|
||||
Reference in New Issue
Block a user