refactor merging of segregated roads

adjust to generalFindMaximum function
moved parallel detection to ratio/absolute based regression testing
considerably improved detection quality using normalised regression lines
only follow initial direction/narrow turns for parallel detection
This commit is contained in:
Moritz Kobitzsch
2016-12-06 13:22:51 +01:00
parent f7ad2e1e26
commit e6ff17ab2a
40 changed files with 2397 additions and 949 deletions
+66 -2
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_EXTRACTOR_GEOJSON_DEBUG_POLICIES
#define OSRM_EXTRACTOR_GEOJSON_DEBUG_POLICIES
#include <algorithm>
#include <vector>
#include "extractor/query_node.hpp"
@@ -11,6 +12,8 @@
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "util/coordinate.hpp"
#include "util/geojson_debug_policy_toolkit.hpp"
#include <boost/optional.hpp>
@@ -18,8 +21,9 @@ namespace osrm
{
namespace extractor
{
// generate a visualisation of an intersection, printing the coordinates used for angle calculation
struct IntersectionPrinter
template <typename IntersectionType> struct IntersectionPrinter
{
IntersectionPrinter(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<extractor::QueryNode> &node_coordinates,
@@ -28,7 +32,7 @@ struct IntersectionPrinter
// renders the used coordinate locations for all entries/as well as the resulting
// intersection-classification
util::json::Array operator()(const NodeID intersection_node,
const extractor::guidance::Intersection &intersection,
const IntersectionType &intersection,
const boost::optional<util::json::Object> &node_style = {},
const boost::optional<util::json::Object> &way_style = {}) const;
@@ -37,6 +41,66 @@ struct IntersectionPrinter
const extractor::guidance::CoordinateExtractor &coordinate_extractor;
};
// IMPLEMENTATION
template <typename IntersectionType>
IntersectionPrinter<IntersectionType>::IntersectionPrinter(
const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<extractor::QueryNode> &node_coordinates,
const extractor::guidance::CoordinateExtractor &coordinate_extractor)
: node_based_graph(node_based_graph), node_coordinates(node_coordinates),
coordinate_extractor(coordinate_extractor)
{
}
template <typename IntersectionType>
util::json::Array IntersectionPrinter<IntersectionType>::
operator()(const NodeID intersection_node,
const IntersectionType &intersection,
const boost::optional<util::json::Object> &node_style,
const boost::optional<util::json::Object> &way_style) const
{
// request the number of lanes. This process needs to be in sync with what happens over at
// intersection_generator
const auto intersection_lanes =
intersection.FindMaximum(guidance::makeExtractLanesForRoad(node_based_graph));
std::vector<util::Coordinate> coordinates;
coordinates.reserve(intersection.size());
coordinates.push_back(node_coordinates[intersection_node]);
const auto road_to_coordinate = [&](const auto &road) {
const constexpr auto FORWARD = false;
const auto to_node = node_based_graph.GetTarget(road.eid);
return coordinate_extractor.GetCoordinateAlongRoad(
intersection_node, road.eid, FORWARD, to_node, intersection_lanes);
};
std::transform(intersection.begin(),
intersection.end(),
std::back_inserter(coordinates),
road_to_coordinate);
util::json::Array features;
features.values.push_back(
util::makeFeature("MultiPoint", makeJsonArray(coordinates), node_style));
if (coordinates.size() > 1)
{
std::vector<util::Coordinate> line_coordinates(2);
line_coordinates[0] = coordinates.front();
const auto coordinate_to_line = [&](const util::Coordinate coordinate) {
line_coordinates[1] = coordinate;
return util::makeFeature("LineString", makeJsonArray(line_coordinates), way_style);
};
std::transform(std::next(coordinates.begin()),
coordinates.end(),
std::back_inserter(features.values),
coordinate_to_line);
}
return features;
}
} /* namespace extractor */
} /* namespace osrm */
+7
View File
@@ -12,6 +12,7 @@ const bool constexpr INVERT = true;
// what angle is interpreted as going straight
const double constexpr STRAIGHT_ANGLE = 180.;
const double constexpr ORTHOGONAL_ANGLE = 90.;
// if a turn deviates this much from going straight, it will be kept straight
const double constexpr MAXIMAL_ALLOWED_NO_TURN_DEVIATION = 3.;
// angle that lies between two nearly indistinguishable roads
@@ -36,6 +37,12 @@ const int constexpr MAX_SLIPROAD_THRESHOLD = 250;
// category).
const double constexpr PRIORITY_DISTINCTION_FACTOR = 1.75;
// the lane width we assume for a single lane
const auto constexpr ASSUMED_LANE_WIDTH = 3.25;
// how far apart can roads be at the most, when thinking about merging them?
const auto constexpr MERGABLE_ANGLE_DIFFERENCE = 95.0;
} // namespace guidance
} // namespace extractor
} // namespace osrm
+91 -33
View File
@@ -8,15 +8,15 @@
#include <type_traits>
#include <vector>
#include "extractor/guidance/turn_instruction.hpp"
#include "util/bearing.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" // EdgeID
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include "extractor/guidance/turn_instruction.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm/min_element.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/range/algorithm/count_if.hpp>
namespace osrm
{
@@ -36,8 +36,8 @@ struct IntersectionShapeData
inline auto makeCompareShapeDataByBearing(const double base_bearing)
{
return [base_bearing](const auto &lhs, const auto &rhs) {
return util::angleBetweenBearings(base_bearing, lhs.bearing) <
util::angleBetweenBearings(base_bearing, rhs.bearing);
return util::bearing::angleBetween(lhs.bearing, base_bearing) <
util::bearing::angleBetween(rhs.bearing, base_bearing);
};
}
@@ -48,6 +48,13 @@ inline auto makeCompareAngularDeviation(const double angle)
};
}
inline auto makeExtractLanesForRoad(const util::NodeBasedDynamicGraph &node_based_graph)
{
return [&node_based_graph](const auto &road) {
return node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
};
}
// 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
struct IntersectionViewData : IntersectionShapeData
@@ -108,11 +115,60 @@ struct ConnectedRoad final : IntersectionViewData
};
// small helper function to print the content of a connected road
std::string toString(const IntersectionShapeData &shape);
std::string toString(const IntersectionViewData &view);
std::string toString(const ConnectedRoad &road);
// Intersections are sorted roads: [0] being the UTurn road, then from sharp right to sharp left.
// common operations shared amongst all intersection types
template <typename Self> struct EnableShapeOps
{
// same as closest turn, but for bearings
auto FindClosestBearing(double bearing) const
{
auto comp = makeCompareShapeDataByBearing(bearing);
return std::min_element(self()->begin(), self()->end(), comp);
}
using IntersectionShape = std::vector<IntersectionShapeData>;
// search a given eid in the intersection
auto FindEid(const EdgeID eid) const
{
return boost::range::find_if(
*self(), [eid](const auto &road) { return road.eid == eid; });
}
// find the maximum value based on a conversion operator
template <typename UnaryProjection> auto FindMaximum(UnaryProjection converter) const
{
BOOST_ASSERT(!self()->empty());
auto initial = converter(self()->front());
const auto extract_maximal_value = [&initial, converter](const auto &road) {
initial = std::max(initial, converter(road));
return false;
};
boost::range::find_if(*self(), extract_maximal_value);
return initial;
}
// find the maximum value based on a conversion operator and a predefined initial value
template <typename UnaryPredicate> auto Count(UnaryPredicate detector) const
{
BOOST_ASSERT(!self()->empty());
return boost::range::count_if(*self(), detector);
}
private:
auto self() { return static_cast<Self *>(this); }
auto self() const { return static_cast<const Self *>(this); }
};
struct IntersectionShape final : std::vector<IntersectionShapeData>, //
EnableShapeOps<IntersectionShape> //
{
using Base = std::vector<IntersectionShapeData>;
};
// Common operations shared among IntersectionView and Intersections.
// Inherit to enable those operations on your compatible type. CRTP pattern.
@@ -123,12 +179,13 @@ template <typename Self> struct EnableIntersectionOps
auto findClosestTurn(double angle) const
{
auto comp = makeCompareAngularDeviation(angle);
return std::min_element(self()->begin(), self()->end(), comp);
return boost::range::min_element(*self(), comp);
}
// Check validity of the intersection object. We assume a few basic properties every set of
// connected roads should follow throughout guidance pre-processing. This utility function
// allows checking intersections for validity
/* Check validity of the intersection object. We assume a few basic properties every set of
* connected roads should follow throughout guidance pre-processing. This utility function
* allows checking intersections for validity
*/
auto valid() const
{
if (self()->empty())
@@ -149,26 +206,6 @@ template <typename Self> struct EnableIntersectionOps
return true;
}
// Given all possible turns which is the highest connected number of lanes per turn.
// This value is used for example during generation of intersections.
auto getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &graph) const
{
const std::function<std::uint8_t(const ConnectedRoad &)> to_lane_count =
[&](const ConnectedRoad &road) {
return graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
};
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 = *self() | boost::adaptors::transformed(to_lane_count);
boost::range::find_if(view, extract_maximal_value);
return max_lanes;
}
// Returns the UTurn road we took to arrive at this intersection.
const auto &getUTurnRoad() const { return self()->operator[](0); }
@@ -191,31 +228,52 @@ template <typename Self> struct EnableIntersectionOps
auto isDeadEnd() const
{
auto pred = [](const auto &road) { return road.entry_allowed; };
return !std::any_of(self()->begin() + 1, self()->end(), pred);
return std::none_of(self()->begin() + 1, self()->end(), pred);
}
// Returns the number of roads we can enter at this intersection, respectively.
auto countEnterable() const
{
auto pred = [](const auto &road) { return road.entry_allowed; };
return std::count_if(self()->begin(), self()->end(), pred);
return boost::range::count_if(*self(), pred);
}
// Returns the number of roads we can not enter at this intersection, respectively.
auto countNonEnterable() const { return self()->size() - self()->countEnterable(); }
// same as find closests turn but with an additional predicate to allow filtering
// the filter has to return `true` for elements that should be ignored
template <typename UnaryPredicate>
auto findClosestTurn(const double angle, const UnaryPredicate filter) const
{
BOOST_ASSERT(!self()->empty());
const auto candidate = boost::range::min_element(
*self(), [angle, &filter](const auto &lhs, const auto &rhs) {
const auto filtered_lhs = filter(lhs), filtered_rhs = filter(rhs);
const auto deviation_lhs = util::angularDeviation(lhs.angle, angle),
deviation_rhs = util::angularDeviation(rhs.angle, angle);
return std::tie(filtered_lhs, deviation_lhs) <
std::tie(filtered_rhs, deviation_rhs);
});
// make sure only to return valid elements
return filter(*candidate) ? self()->end() : candidate;
}
private:
auto self() { return static_cast<Self *>(this); }
auto self() const { return static_cast<const Self *>(this); }
};
struct IntersectionView final : std::vector<IntersectionViewData>, //
EnableShapeOps<IntersectionView>, //
EnableIntersectionOps<IntersectionView> //
{
using Base = std::vector<IntersectionViewData>;
};
struct Intersection final : std::vector<ConnectedRoad>, //
EnableShapeOps<Intersection>, //
EnableIntersectionOps<Intersection> //
{
using Base = std::vector<ConnectedRoad>;
@@ -4,6 +4,7 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_normalization_operation.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "util/attributes.hpp"
@@ -22,6 +23,13 @@ namespace extractor
{
namespace guidance
{
struct IntersectionGenerationParameters
{
NodeID nid;
EdgeID via_eid;
};
// The Intersection Generator is given a turn location and generates an intersection representation
// from it. For this all turn possibilities are analysed.
// We consider turn restrictions to indicate possible turns. U-turns are generated based on profile
@@ -63,8 +71,8 @@ class IntersectionGenerator
// more than a single next road. This function skips over degree two nodes to find coorect input
// for GetConnectedRoads.
OSRM_ATTR_WARN_UNUSED
std::pair<NodeID, EdgeID> SkipDegreeTwoNodes(const NodeID starting_node,
const EdgeID via_edge) const;
IntersectionGenerationParameters SkipDegreeTwoNodes(const NodeID starting_node,
const EdgeID via_edge) const;
// Allow access to the coordinate extractor for all owners
const CoordinateExtractor &GetCoordinateExtractor() const;
@@ -73,7 +81,7 @@ class IntersectionGenerator
// the node reached from `from_node` via `via_eid`. The resulting candidates have to be analysed
// for their actual instructions later on.
// The switch for `use_low_precision_angles` enables a faster mode that will procude less
// accurate coordinates. It should be good enough to check order of turns, find striaghtmost
// accurate coordinates. It should be good enough to check order of turns, find straightmost
// turns. Even good enough to do some simple angle verifications. It is mostly available to
// allow for faster graph traversal in the extraction phase.
OSRM_ATTR_WARN_UNUSED
@@ -98,7 +106,7 @@ class IntersectionGenerator
const EdgeID entering_via_edge,
const IntersectionShape &normalised_intersection,
const IntersectionShape &intersection,
const std::vector<std::pair<EdgeID, EdgeID>> &merging_map) const;
const std::vector<IntersectionNormalizationOperation> &merging_map) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
@@ -508,15 +508,15 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
// even reverse the direction. Since we don't want to compute actual turns but simply
// try to find whether there is a turn going to the opposite direction of our obvious
// turn, this should be alright.
NodeID new_node;
const auto previous_intersection = [&]() {
EdgeID turn_edge;
std::tie(new_node, turn_edge) = intersection_generator.SkipDegreeTwoNodes(
const auto previous_intersection = [&]() -> IntersectionView {
const auto parameters = intersection_generator.SkipDegreeTwoNodes(
node_at_intersection, intersection[0].eid);
return intersection_generator.GetConnectedRoads(new_node, turn_edge);
if (node_based_graph.GetTarget(parameters.via_eid) == node_at_intersection)
return {};
return intersection_generator.GetConnectedRoads(parameters.nid, parameters.via_eid);
}();
if (new_node != node_at_intersection)
if (!previous_intersection.empty())
{
const auto continue_road = intersection[best_continue];
for (const auto &comparison_road : previous_intersection)
@@ -0,0 +1,25 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZATION_OPERATION_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZATION_OPERATION_HPP_
#include "util/typedefs.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
struct IntersectionNormalizationOperation
{
// the source of the merge, not part of the intersection after the merge is performed.
EdgeID merged_eid;
// the edge that is covering the `merged_eid`
EdgeID into_eid;
};
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /*OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZATION_OPERATION_HPP_*/
@@ -1,17 +1,17 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
#include "util/typedefs.hpp"
#include "util/attributes.hpp"
#include "util/name_table.hpp"
#include "util/typedefs.hpp"
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_normalization_operation.hpp"
#include "extractor/guidance/mergable_road_detector.hpp"
#include "extractor/query_node.hpp"
#include "extractor/suffix_table.hpp"
#include "util/name_table.hpp"
#include <utility>
#include <vector>
@@ -37,6 +37,11 @@ namespace guidance
class IntersectionNormalizer
{
public:
struct NormalizationResult
{
IntersectionShape normalized_shape;
std::vector<IntersectionNormalizationOperation> performed_merges;
};
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<extractor::QueryNode> &node_coordinates,
const util::NameTable &name_table,
@@ -46,16 +51,13 @@ class IntersectionNormalizer
// The function takes an intersection an converts it to a `perceived` intersection which closer
// represents how a human might experience the intersection
OSRM_ATTR_WARN_UNUSED
std::pair<IntersectionShape, std::vector<std::pair<EdgeID, EdgeID>>>
operator()(const NodeID node_at_intersection, IntersectionShape intersection) const;
NormalizationResult operator()(const NodeID node_at_intersection,
IntersectionShape intersection) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const std::vector<extractor::QueryNode> &node_coordinates;
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
const IntersectionGenerator &intersection_generator;
const MergableRoadDetector mergable_road_detector;
/* 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
@@ -73,12 +75,15 @@ class IntersectionNormalizer
std::size_t first_index,
std::size_t second_index) const;
// A tool called by CanMerge. It checks whether two indices can be merged, not concerned without
// remaining parts of the intersection.
bool InnerCanMerge(const NodeID intersection_node,
const IntersectionShape &intersection,
std::size_t first_index,
std::size_t second_index) const;
// Perform an Actual Merge
IntersectionNormalizationOperation
DetermineMergeDirection(const IntersectionShapeData &lhs,
const IntersectionShapeData &rhs) const;
IntersectionShapeData MergeRoads(const IntersectionShapeData &destination,
const IntersectionShapeData &source) const;
IntersectionShapeData MergeRoads(const IntersectionNormalizationOperation direction,
const IntersectionShapeData &lhs,
const IntersectionShapeData &rhs) const;
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
// one.
@@ -92,8 +97,8 @@ class IntersectionNormalizer
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
// 160
OSRM_ATTR_WARN_UNUSED
std::pair<IntersectionShape, std::vector<std::pair<EdgeID, EdgeID>>>
MergeSegregatedRoads(const NodeID intersection_node, IntersectionShape intersection) const;
NormalizationResult MergeSegregatedRoads(const NodeID intersection_node,
IntersectionShape intersection) const;
// The counterpiece to mergeSegregatedRoads. While we can adjust roads that split up at the
// intersection itself, it can also happen that intersections are connected to joining roads.
@@ -0,0 +1,155 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
#define OSRM_EXTRACTOR_GUIDANCE_MERGEABLE_ROADS
#include "extractor/guidance/intersection.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <cstdint>
#include <functional>
#include <limits>
#include <vector>
namespace osrm
{
//FWD declarations
namespace util
{
class NameTable;
} // namespace util
namespace extractor
{
struct QueryNode;
class SuffixTable;
namespace guidance
{
class IntersectionGenerator;
class CoordinateExtractor;
class MergableRoadDetector
{
public:
// in case we have to change the mode we are operating on
using MergableRoadData = IntersectionShapeData;
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_coordinates,
const IntersectionGenerator &intersection_generator,
const CoordinateExtractor &coordinate_extractor,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
// OSM ways tend to be modelled as separate ways for different directions. This is often due to
// small gras strips in the middle between the two directions or due to pedestrian islands at
// intersections.
//
// To reduce unnecessary information due to these artificial intersections (which are not
// actually perceived as such) we try and merge these for our internal representation to both
// get better perceived turn angles and get a better reprsentation of our intersections in
// general.
//
// i h i,h
// | | |
// | | |
// b - - - v - - - g |
// > a < is transformed into: b,c - - - a - - - g,f
// c - - - ^ - - - f |
// | | |
// | | |
// d e d,e
bool CanMergeRoad(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const;
// check if a road cannot influence the merging of the other. This is necessary to prevent
// situations with more than two roads that could participate in a merge
bool IsDistinctFrom(const MergableRoadData &lhs, const MergableRoadData &rhs) const;
private:
// check if two name ids can be seen as identical (in presence of refs/others)
// in our case this translates into no name announcement in either direction (lhs->rhs and
// rhs->lhs)
bool HaveIdenticalNames(const NameID lhs, const NameID rhs) const;
// When it comes to merging roads, we need to find out if two ways actually represent the
// same road. This check tries to identify roads which are the same road in opposite directions
bool EdgeDataSupportsMerge(const util::NodeBasedEdgeData &lhs_edge_data,
const util::NodeBasedEdgeData &rhs_edge_data) const;
// Detect traffic loops.
// Since OSRM cannot handle loop edges, we cannot directly see a connection between a node and
// itself. We need to skip at least a single node in between.
bool IsTrafficLoop(const NodeID intersection_node, const MergableRoadData &road) const;
// Detector to check if we are looking at roads splitting up just prior to entering an
// intersection:
//
// c
// / |
// a -< |
// \ |
// b
//
// A common scheme in OSRM is that roads spit up in separate ways when approaching an
// intersection. This detector tries to detect these narrow triangles which usually just offer a
// small island for pedestrians in the middle.
bool IsNarrowTriangle(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const;
// Detector to check for whether two roads are following the same direction.
// If roads don't end up right at a connected intersection, we could look at a situation like
//
// __________________________
// /
// ---
// \__________________________
//
// This detector tries to find out about whether two roads are parallel after the separation
bool HaveSameDirection(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const;
// Detector for small traffic islands. If a road is splitting up, just to connect again later,
// we don't wan't to have this information within our list of intersections/possible turn
// locations.
//
// ___________
// ---<___________>-----
//
//
// Would feel just like a single straight road to a driver and should be represented as such in
// our engine
bool IsTrafficIsland(const NodeID intersection_node,
const MergableRoadData &lhs,
const MergableRoadData &rhs) const;
// A negative detector, preventing a merge, trying to detect link roads between two main roads.
//
// d - - - - - - - - e - f
// . / '
// a - - - b - - - - - - c
//
// The detector wants to prevent merges that are connected to `b-e`
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
const util::NodeBasedDynamicGraph &node_based_graph;
const std::vector<QueryNode> &node_coordinates;
const IntersectionGenerator &intersection_generator;
const CoordinateExtractor &coordinate_extractor;
// name detection
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
};
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif
@@ -57,7 +57,6 @@ struct LengthLimitedCoordinateAccumulator
{
LengthLimitedCoordinateAccumulator(
const extractor::guidance::CoordinateExtractor &coordinate_extractor,
const util::NodeBasedDynamicGraph &node_based_graph,
const double max_length);
/*
@@ -78,11 +77,12 @@ struct LengthLimitedCoordinateAccumulator
*/
void update(const NodeID from_node, const EdgeID via_edge, const NodeID to_node);
const extractor::guidance::CoordinateExtractor &coordinate_extractor;
const util::NodeBasedDynamicGraph &node_based_graph;
const double max_length;
double accumulated_length;
double accumulated_length = 0;
std::vector<util::Coordinate> coordinates;
private:
const extractor::guidance::CoordinateExtractor &coordinate_extractor;
const double max_length;
};
/*
@@ -105,13 +105,40 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
*/
boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const Intersection &intersection,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph) const;
private:
const NameID desired_name_id;
const bool requires_entry;
};
/* Following only a straight road
* Follow only the straightmost turn, as long as its the only choice or has the desired name
*/
struct SelectStraightmostRoadByNameAndOnlyChoice
{
SelectStraightmostRoadByNameAndOnlyChoice(const NameID desired_name_id,
const double initial_bearing,
const bool requires_entry);
/*
* !! REQUIRED - Function for the use of TraverseRoad in the graph walker.
* The operator() needs to return (if any is found) the next road to continue in the graph
* traversal. If no such edge is found, return {} is allowed. Usually you want to choose some
* form of obious turn to follow.
*/
boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph) const;
private:
const NameID desired_name_id;
const double initial_bearing;
const bool requires_entry;
};
// find the next intersection given a hop limit
struct IntersectionFinderAccumulator
{
@@ -166,8 +193,9 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
return {};
// look at the next intersection
const auto next_intersection =
intersection_generator.GetConnectedRoads(current_node_id, current_edge_id);
const constexpr auto LOW_PRECISION = true;
const auto next_intersection = intersection_generator.GetConnectedRoads(
current_node_id, current_edge_id, LOW_PRECISION);
// don't follow u-turns or go past our initial intersection
if (next_intersection.size() <= 1)
@@ -235,7 +263,7 @@ struct DistanceToNextIntersectionAccumulator
using namespace util::coordinate_calculation;
const auto coords = extractor.GetForwardCoordinatesAlongRoad(start, onto);
distance += getLength(coords, &haversineDistance);
distance += getLength(coords.begin(), coords.end(), &haversineDistance);
}
const extractor::guidance::CoordinateExtractor &extractor;
+4 -5
View File
@@ -4,6 +4,7 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_normalization_operation.hpp"
#include "extractor/guidance/intersection_normalizer.hpp"
#include "extractor/guidance/motorway_handler.hpp"
#include "extractor/guidance/roundabout_handler.hpp"
@@ -62,11 +63,9 @@ class TurnAnalysis
{
// the basic shape, containing all turns
IntersectionShape intersection_shape;
// normalised shape, merged some roads into others, adjusted bearings
// see intersection_normaliser for further explanations
IntersectionShape normalised_intersection_shape;
// map containing information about which road was merged into which
std::vector<std::pair<EdgeID, EdgeID>> merging_map;
// normalized shape, merged some roads into others, adjusted bearings
// see intersection_normalizer for further explanations
IntersectionNormalizer::NormalizationResult annotated_normalized_shape;
};
OSRM_ATTR_WARN_UNUSED
ShapeResult ComputeIntersectionShapes(const NodeID node_at_center_of_intersection) const;