#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 #include 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 performed_merges; }; IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph, const EdgeBasedNodeDataContainer &node_data_container, const std::vector &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_ */