- moves collapse into a dedicated set of functions / files - make collapse scenarios distinct (slight performance cost) - reduce verbosity for short name segments (now actually working, was supposed to do so before)
125 lines
5.4 KiB
C++
125 lines
5.4 KiB
C++
#ifndef OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_
|
|
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_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 <utility>
|
|
#include <vector>
|
|
|
|
namespace osrm
|
|
{
|
|
namespace extractor
|
|
{
|
|
namespace guidance
|
|
{
|
|
|
|
/*
|
|
* An intersection is a central part in computing guidance decisions. However the model in OSM and
|
|
* the view we want to use in guidance are not necessarily the same thing. We have to account for
|
|
* some models that are chosen explicitly in OSM and that don't actually describe how a human would
|
|
* experience an intersection.
|
|
*
|
|
* For example, if a small pedestrian island is located at a traffic light right in the middle of a
|
|
* road, OSM tends to model the road as two separate ways. A human would consider these two ways a
|
|
* single road, though. In this normalizer, we try to account for these subtle differences between
|
|
* OSM data and human perception to improve our decision base for guidance later on.
|
|
*/
|
|
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,
|
|
const SuffixTable &street_name_suffix_table,
|
|
const IntersectionGenerator &intersection_generator);
|
|
|
|
// 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
|
|
NormalizationResult operator()(const NodeID node_at_intersection,
|
|
IntersectionShape intersection) const;
|
|
|
|
private:
|
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
|
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
|
|
* MergeSegregatedRoads. It also checks for neighboring merges.
|
|
* 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.
|
|
* c c
|
|
* / /
|
|
* a - b -> a - b - (c,d) but not a - b d -> a,b,(cde)
|
|
* \ \
|
|
* d e
|
|
*/
|
|
bool CanMerge(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 double opposite_bearing) const;
|
|
|
|
// Merge segregated roads to omit invalid turns in favor of treating segregated roads as
|
|
// one.
|
|
// This function combines roads the following way:
|
|
//
|
|
// * *
|
|
// * is converted to *
|
|
// v ^ +
|
|
// v ^ +
|
|
//
|
|
// The treatment results in a straight turn angle of 180º rather than a turn angle of approx
|
|
// 160
|
|
OSRM_ATTR_WARN_UNUSED
|
|
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.
|
|
//
|
|
// * *
|
|
// * is converted to *
|
|
// v a --- a ---
|
|
// v ^ +
|
|
// v ^ +
|
|
// b
|
|
//
|
|
// for the local view of b at a.
|
|
OSRM_ATTR_WARN_UNUSED
|
|
IntersectionShape AdjustBearingsForMergeAtDestination(const NodeID node_at_intersection,
|
|
IntersectionShape intersection) const;
|
|
};
|
|
|
|
} // namespace guidance
|
|
} // namespace extractor
|
|
} // namespace osrm
|
|
|
|
#endif /* OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_NORMALIZER_HPP_ */
|