Abstracts away over differences in IntersectionView and Intersection.

Usage:

    struct MyIntersection : EnableIntersectionOps<MyIntersection> {

    };

Done.

We require MyIntersection having at least the member attributes from
IntersectionViewData but don't enforce a inheritance hierarchy.
This commit is contained in:
Daniel J. Hofmann 2016-12-02 12:02:42 +01:00 committed by Moritz Kobitzsch
parent 928a6f0c7d
commit 9d8b92f418
5 changed files with 47 additions and 62 deletions

View File

@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_HPP_ #define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_HPP_
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
@ -27,11 +28,19 @@ struct IntersectionShapeData
inline auto makeCompareShapeDataByBearing(const double base_bearing) inline auto makeCompareShapeDataByBearing(const double base_bearing)
{ {
return [base_bearing](const IntersectionShapeData &lhs, const IntersectionShapeData &rhs) { return [base_bearing](const auto &lhs, const auto &rhs) {
return util::bearing::angleBetweenBearings(base_bearing, lhs.bearing) < return util::bearing::angleBetweenBearings(base_bearing, lhs.bearing) <
util::bearing::angleBetweenBearings(base_bearing, rhs.bearing); util::bearing::angleBetweenBearings(base_bearing, rhs.bearing);
}; };
}; }
inline auto makeCompareAngularDeviation(const double angle)
{
return [angle](const auto &lhs, const auto &rhs) {
return util::guidance::angularDeviation(lhs.angle, angle) <
util::guidance::angularDeviation(rhs.angle, angle);
};
}
// When viewing an intersection from an incoming edge, we can transform a shape into a view which // When viewing an intersection from an incoming edge, we can transform a shape into a view which
// gives additional information on angles and whether a turn is allowed // gives additional information on angles and whether a turn is allowed
@ -98,7 +107,25 @@ std::string toString(const ConnectedRoad &road);
using IntersectionShape = std::vector<IntersectionShapeData>; using IntersectionShape = std::vector<IntersectionShapeData>;
struct IntersectionView final : std::vector<IntersectionViewData> // Common operations shared among IntersectionView and Intersections.
// Inherit to enable those operations on your compatible type. CRTP pattern.
template <typename Self> struct EnableIntersectionOps
{
// Find the turn whose angle offers the least angular deviation to the specified angle
// For turn angles [0, 90, 260] and a query of 180 we return the 260 degree turn.
auto findClosestTurn(double angle) const
{
auto comp = makeCompareAngularDeviation(angle);
return std::min_element(self()->begin(), self()->end(), comp);
}
private:
auto self() { return static_cast<Self *>(this); }
auto self() const { return static_cast<const Self *>(this); }
};
struct IntersectionView final : std::vector<IntersectionViewData>, //
EnableIntersectionOps<IntersectionView> //
{ {
using Base = std::vector<IntersectionViewData>; using Base = std::vector<IntersectionViewData>;
@ -106,21 +133,12 @@ struct IntersectionView final : std::vector<IntersectionViewData>
{ {
return std::is_sorted(begin(), end(), std::mem_fn(&IntersectionViewData::CompareByAngle)); return std::is_sorted(begin(), end(), std::mem_fn(&IntersectionViewData::CompareByAngle));
}; };
Base::iterator findClosestTurn(double angle);
Base::const_iterator findClosestTurn(double angle) const;
}; };
struct Intersection final : std::vector<ConnectedRoad> struct Intersection final : std::vector<ConnectedRoad>, //
EnableIntersectionOps<Intersection> //
{ {
using Base = std::vector<ConnectedRoad>; using Base = std::vector<ConnectedRoad>;
/*
* find the turn whose angle offers the least angularDeviation to the specified angle
* E.g. for turn angles [0,90,260] and a query of 180 we return the 260 degree turn (difference
* 80 over the difference of 90 to the 90 degree turn)
*/
Base::iterator findClosestTurn(double angle);
Base::const_iterator findClosestTurn(double angle) const;
/* /*
* Check validity of the intersection object. We assume a few basic properties every set of * Check validity of the intersection object. We assume a few basic properties every set of
@ -134,9 +152,6 @@ struct Intersection final : std::vector<ConnectedRoad>
std::uint8_t getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &) const; std::uint8_t getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &) const;
}; };
Intersection::const_iterator findClosestTurn(const Intersection &intersection, const double angle);
Intersection::iterator findClosestTurn(Intersection &intersection, const double angle);
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor
} // namespace osrm } // namespace osrm

View File

@ -57,16 +57,17 @@ class IntersectionNormalizer
const IntersectionGenerator &intersection_generator; const IntersectionGenerator &intersection_generator;
// check if two indices in an intersection can be seen as a single road in the perceived /* check if two indices in an intersection can be seen as a single road in the perceived
// intersection representation. See below for an example. Utility function for * intersection representation. See below for an example. Utility function for
// MergeSegregatedRoads. It also checks for neighboring merges. * MergeSegregatedRoads. It also checks for neighboring merges.
// This is due possible segments where multiple roads could end up being merged into one. * This is due possible segments where multiple roads could end up being merged into one.
// We only support merging two roads, not three or more, though. * We only support merging two roads, not three or more, though.
// c c * c c
// / / * / /
// a - b -> a - b - (c,d) but not a - b d -> a,b,(cde) * a - b -> a - b - (c,d) but not a - b d -> a,b,(cde)
// \ \ * \ \
// d e * d e
*/
bool CanMerge(const NodeID intersection_node, bool CanMerge(const NodeID intersection_node,
const IntersectionShape &intersection, const IntersectionShape &intersection,
std::size_t first_index, std::size_t first_index,

View File

@ -14,7 +14,9 @@ IntersectionPrinter::IntersectionPrinter(
const std::vector<extractor::QueryNode> &node_coordinates, const std::vector<extractor::QueryNode> &node_coordinates,
const extractor::guidance::CoordinateExtractor &coordinate_extractor) const extractor::guidance::CoordinateExtractor &coordinate_extractor)
: node_based_graph(node_based_graph), node_coordinates(node_coordinates), : node_based_graph(node_based_graph), node_coordinates(node_coordinates),
coordinate_extractor(coordinate_extractor){}; coordinate_extractor(coordinate_extractor)
{
}
util::json::Array IntersectionPrinter:: util::json::Array IntersectionPrinter::
operator()(const NodeID intersection_node, operator()(const NodeID intersection_node,

View File

@ -55,7 +55,7 @@ double GetOffsetCorrectionFactor(const RoadClassification &road_classification)
default: default:
return 1.0; return 1.0;
}; };
}; }
} }
CoordinateExtractor::CoordinateExtractor( CoordinateExtractor::CoordinateExtractor(

View File

@ -70,39 +70,6 @@ std::string toString(const ConnectedRoad &road)
return result; return result;
} }
IntersectionView::Base::iterator IntersectionView::findClosestTurn(double angle)
{
// use the const operator to avoid code duplication
return begin() +
std::distance(cbegin(),
static_cast<const IntersectionView *>(this)->findClosestTurn(angle));
}
IntersectionView::Base::const_iterator IntersectionView::findClosestTurn(double angle) const
{
return std::min_element(
begin(), end(), [angle](const IntersectionViewData &lhs, const IntersectionViewData &rhs) {
return util::guidance::angularDeviation(lhs.angle, angle) <
util::guidance::angularDeviation(rhs.angle, angle);
});
}
Intersection::Base::iterator Intersection::findClosestTurn(double angle)
{
// use the const operator to avoid code duplication
return begin() +
std::distance(cbegin(), static_cast<const Intersection *>(this)->findClosestTurn(angle));
}
Intersection::Base::const_iterator Intersection::findClosestTurn(double angle) const
{
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 bool Intersection::valid() const
{ {
return !empty() && return !empty() &&