diff --git a/routing/loaded_path_segment.hpp b/routing/loaded_path_segment.hpp index 985feeae40..5123faa3c3 100644 --- a/routing/loaded_path_segment.hpp +++ b/routing/loaded_path_segment.hpp @@ -20,8 +20,6 @@ struct FeatureGraphNode; namespace turns { -using TSeg = OsrmMappingTypes::FtSeg; - /*! * \brief The LoadedPathSegment struct is a representation of a single node path. * It unpacks and stores information about path and road type flags. @@ -38,21 +36,14 @@ struct LoadedPathSegment TNodeId m_nodeId; vector m_lanes; - // General constructor. - LoadedPathSegment(RoutingMapping & mapping, Index const & index, - RawPathData const & osrmPathSegment); - // Special constructor for side nodes. Splits OSRM node by information from the FeatureGraphNode. - LoadedPathSegment(RoutingMapping & mapping, Index const & index, - RawPathData const & osrmPathSegment, FeatureGraphNode const & startGraphNode, - FeatureGraphNode const & endGraphNode, bool isStartNode, bool isEndNode); - -private: - // Load information about road, that described as the sequence of FtSegs and start/end indexes in - // in it. For the side case, it has information about start/end graph nodes. - void LoadPathGeometry(buffer_vector const & buffer, size_t startIndex, - size_t endIndex, Index const & index, RoutingMapping & mapping, - FeatureGraphNode const & startGraphNode, - FeatureGraphNode const & endGraphNode, bool isStartNode, bool isEndNode); + LoadedPathSegment(TEdgeWeight weight, TNodeId nodeId) + : m_highwayClass(ftypes::HighwayClass::Undefined) + , m_onRoundabout(false) + , m_isLink(false) + , m_weight(weight) + , m_nodeId(nodeId) + { + } }; } // namespace routing } // namespace turns diff --git a/routing/loaded_path_segment.cpp b/routing/osrm_path_segment_factory.cpp similarity index 67% rename from routing/loaded_path_segment.cpp rename to routing/osrm_path_segment_factory.cpp index bd83f7215b..4469cf2f23 100644 --- a/routing/loaded_path_segment.cpp +++ b/routing/osrm_path_segment_factory.cpp @@ -1,4 +1,4 @@ -#include "routing/loaded_path_segment.hpp" +#include "routing/osrm_path_segment_factory.hpp" #include "routing/routing_mapping.hpp" #include "indexer/feature.hpp" @@ -8,43 +8,16 @@ #include "base/buffer_vector.hpp" -namespace routing -{ -namespace turns +namespace { // Osrm multiples seconds to 10, so we need to divide it back. double constexpr kOSRMWeightToSecondsMultiplier = 1. / 10.; -LoadedPathSegment::LoadedPathSegment(RoutingMapping & mapping, Index const & index, - RawPathData const & osrmPathSegment) - : m_highwayClass(ftypes::HighwayClass::Undefined) - , m_onRoundabout(false) - , m_isLink(false) - , m_weight(osrmPathSegment.segmentWeight * kOSRMWeightToSecondsMultiplier) - , m_nodeId(osrmPathSegment.node) -{ - buffer_vector buffer; - mapping.m_segMapping.ForEachFtSeg(osrmPathSegment.node, MakeBackInsertFunctor(buffer)); - if (buffer.empty()) - { - LOG(LERROR, ("Can't unpack geometry for map:", mapping.GetCountryName(), " node: ", - osrmPathSegment.node)); - alohalytics::Stats::Instance().LogEvent( - "RouteTracking_UnpackingError", - {{"node", strings::to_string(osrmPathSegment.node)}, - {"map", mapping.GetCountryName()}, - {"version", strings::to_string(mapping.GetMwmId().GetInfo()->GetVersion())}}); - return; - } - LoadPathGeometry(buffer, 0, buffer.size(), index, mapping, FeatureGraphNode(), FeatureGraphNode(), - false /* isStartNode */, false /*isEndNode*/); -} - -void LoadedPathSegment::LoadPathGeometry(buffer_vector const & buffer, size_t startIndex, - size_t endIndex, Index const & index, RoutingMapping & mapping, - FeatureGraphNode const & startGraphNode, - FeatureGraphNode const & endGraphNode, bool isStartNode, - bool isEndNode) +void LoadPathGeometry(buffer_vector const & buffer, size_t startIndex, + size_t endIndex, Index const & index, routing::RoutingMapping & mapping, + routing::FeatureGraphNode const & startGraphNode, + routing::FeatureGraphNode const & endGraphNode, bool isStartNode, + bool isEndNode, routing::turns::LoadedPathSegment & loadPathGeometry) { ASSERT_LESS(startIndex, endIndex, ()); ASSERT_LESS_OR_EQUAL(endIndex, buffer.size(), ()); @@ -54,7 +27,7 @@ void LoadedPathSegment::LoadPathGeometry(buffer_vector const & buffer, auto const & segment = buffer[k]; if (!segment.IsValid()) { - m_path.clear(); + loadPathGeometry.m_path.clear(); return; } // Load data from drive. @@ -75,13 +48,13 @@ void LoadedPathSegment::LoadPathGeometry(buffer_vector const & buffer, if (startIdx < endIdx) { for (auto idx = startIdx; idx <= endIdx; ++idx) - m_path.push_back(ft.GetPoint(idx)); + loadPathGeometry.m_path.push_back(ft.GetPoint(idx)); } else { // I use big signed type because endIdx can be 0. for (int64_t idx = startIdx; idx >= static_cast(endIdx); --idx) - m_path.push_back(ft.GetPoint(idx)); + loadPathGeometry.m_path.push_back(ft.GetPoint(idx)); } // Load lanes if it is a last segment before junction. @@ -97,33 +70,59 @@ void LoadedPathSegment::LoadPathGeometry(buffer_vector const & buffer, directionType = (startIdx < endIdx) ? Metadata::FMD_TURN_LANES_FORWARD : Metadata::FMD_TURN_LANES_BACKWARD; } - ParseLanes(md.Get(directionType), m_lanes); + ParseLanes(md.Get(directionType), loadPathGeometry.m_lanes); } // Calculate node flags. - m_onRoundabout |= ftypes::IsRoundAboutChecker::Instance()(ft); - m_isLink |= ftypes::IsLinkChecker::Instance()(ft); - m_highwayClass = ftypes::GetHighwayClass(ft); + loadPathGeometry.m_onRoundabout |= ftypes::IsRoundAboutChecker::Instance()(ft); + loadPathGeometry.m_isLink |= ftypes::IsLinkChecker::Instance()(ft); + loadPathGeometry.m_highwayClass = ftypes::GetHighwayClass(ft); string name; ft.GetName(FeatureType::DEFAULT_LANG, name); if (!name.empty()) - m_name = name; + loadPathGeometry.m_name = name; } } +} // namespace -LoadedPathSegment::LoadedPathSegment(RoutingMapping & mapping, Index const & index, - RawPathData const & osrmPathSegment, - FeatureGraphNode const & startGraphNode, - FeatureGraphNode const & endGraphNode, bool isStartNode, - bool isEndNode) - : m_highwayClass(ftypes::HighwayClass::Undefined) - , m_onRoundabout(false) - , m_isLink(false) - , m_weight(0) - , m_nodeId(osrmPathSegment.node) +namespace routing +{ +namespace turns +{ +unique_ptr LoadedPathSegmentFactory(RoutingMapping & mapping, + Index const & index, + RawPathData const & osrmPathSegment) +{ + buffer_vector buffer; + mapping.m_segMapping.ForEachFtSeg(osrmPathSegment.node, MakeBackInsertFunctor(buffer)); + unique_ptr loadedPathSegment = + make_unique(osrmPathSegment.segmentWeight * kOSRMWeightToSecondsMultiplier, + osrmPathSegment.node); + if (buffer.empty()) + { + LOG(LERROR, ("Can't unpack geometry for map:", mapping.GetCountryName(), " node: ", + osrmPathSegment.node)); + alohalytics::Stats::Instance().LogEvent( + "RouteTracking_UnpackingError", + {{"node", strings::to_string(osrmPathSegment.node)}, + {"map", mapping.GetCountryName()}, + {"version", strings::to_string(mapping.GetMwmId().GetInfo()->GetVersion())}}); + return loadedPathSegment; + } + LoadPathGeometry(buffer, 0, buffer.size(), index, mapping, FeatureGraphNode(), FeatureGraphNode(), + false /* isStartNode */, false /*isEndNode*/, *loadedPathSegment); + return loadedPathSegment; +} + +unique_ptr LoadedPathSegmentFactory(RoutingMapping & mapping, Index const & index, + RawPathData const & osrmPathSegment, + FeatureGraphNode const & startGraphNode, + FeatureGraphNode const & endGraphNode, + bool isStartNode, bool isEndNode) { ASSERT(isStartNode || isEndNode, ("This function process only corner cases.")); + unique_ptr loadedPathSegment = make_unique(0, osrmPathSegment.node); if (!startGraphNode.segment.IsValid() || !endGraphNode.segment.IsValid()) - return; + return loadedPathSegment; buffer_vector buffer; mapping.m_segMapping.ForEachFtSeg(osrmPathSegment.node, MakeBackInsertFunctor(buffer)); @@ -153,7 +152,7 @@ LoadedPathSegment::LoadedPathSegment(RoutingMapping & mapping, Index const & ind : startGraphNode.node.reverse_offset; // Sum because weights in forward/backward_weight fields are negative. Look osrm_helpers for // more info. - m_weight = wholeWeight + forwardWeight + backwardWeight; + loadedPathSegment->m_weight = wholeWeight + forwardWeight + backwardWeight; } else { @@ -164,7 +163,7 @@ LoadedPathSegment::LoadedPathSegment(RoutingMapping & mapping, Index const & ind node = &endGraphNode.node; if (node) { - m_weight = (osrmPathSegment.node == node->forward_weight) + loadedPathSegment->m_weight = (osrmPathSegment.node == node->forward_weight) ? node->GetForwardWeightPlusOffset() : node->GetReverseWeightPlusOffset(); } } @@ -172,8 +171,9 @@ LoadedPathSegment::LoadedPathSegment(RoutingMapping & mapping, Index const & ind size_t startIndex = isStartNode ? findIntersectingSeg(startGraphNode.segment) : 0; size_t endIndex = isEndNode ? findIntersectingSeg(endGraphNode.segment) + 1 : buffer.size(); LoadPathGeometry(buffer, startIndex, endIndex, index, mapping, startGraphNode, endGraphNode, isStartNode, - isEndNode); - m_weight *= kOSRMWeightToSecondsMultiplier; + isEndNode, *loadedPathSegment); + loadedPathSegment->m_weight *= kOSRMWeightToSecondsMultiplier; + return loadedPathSegment; } } // namespace routing } // namespace turns diff --git a/routing/osrm_path_segment_factory.hpp b/routing/osrm_path_segment_factory.hpp new file mode 100644 index 0000000000..eaed6d5488 --- /dev/null +++ b/routing/osrm_path_segment_factory.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "routing/loaded_path_segment.hpp" + +#include "std/unique_ptr.hpp" + +namespace routing +{ +struct RoutingMapping; +struct RawPathData; +struct FeatureGraphNode; + +namespace turns +{ +using TSeg = OsrmMappingTypes::FtSeg; + +// General constructor. +unique_ptr LoadedPathSegmentFactory(RoutingMapping & mapping, + Index const & index, + RawPathData const & osrmPathSegment); +// Special constructor for side nodes. Splits OSRM node by information from the FeatureGraphNode. +unique_ptr LoadedPathSegmentFactory(RoutingMapping & mapping, Index const & index, + RawPathData const & osrmPathSegment, + FeatureGraphNode const & startGraphNode, + FeatureGraphNode const & endGraphNode, + bool isStartNode, bool isEndNode); +} // namespace routing +} // namespace turns diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index d37922c232..2536b121c8 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -1,5 +1,6 @@ #include "routing/cross_mwm_router.hpp" #include "routing/loaded_path_segment.hpp" +#include "routing/osrm_path_segment_factory.hpp" #include "routing/online_cross_fetcher.hpp" #include "routing/osrm2feature_map.hpp" #include "routing/osrm_helpers.hpp" @@ -28,6 +29,7 @@ #include "std/algorithm.hpp" #include "std/limits.hpp" #include "std/string.hpp" +#include "std/unique_ptr.hpp" #include "3party/osrm/osrm-backend/data_structures/query_edge.hpp" #include "3party/osrm/osrm-backend/data_structures/internal_route_result.hpp" @@ -63,7 +65,7 @@ using RawRouteData = InternalRouteResult; class OSRMRoutingResultGraph : public turns::IRoutingResultGraph { public: - virtual vector const & GetSegments() const override + virtual vector> const & GetSegments() const override { return m_loadedSegments; } @@ -178,13 +180,14 @@ public: bool isEndNode = (segmentIndex == numSegments - 1); if (isStartNode || isEndNode) { - m_loadedSegments.emplace_back(m_routingMapping, m_index, pathSegments[segmentIndex], - m_rawResult.sourceEdge, m_rawResult.targetEdge, isStartNode, - isEndNode); + m_loadedSegments.push_back(turns::LoadedPathSegmentFactory(m_routingMapping, m_index, + pathSegments[segmentIndex], m_rawResult.sourceEdge, + m_rawResult.targetEdge, isStartNode, isEndNode)); } else { - m_loadedSegments.emplace_back(m_routingMapping, m_index, pathSegments[segmentIndex]); + m_loadedSegments.push_back(turns::LoadedPathSegmentFactory(m_routingMapping, m_index, + pathSegments[segmentIndex])); } } } @@ -192,7 +195,7 @@ public: ~OSRMRoutingResultGraph() {} private: - vector m_loadedSegments; + vector> m_loadedSegments; RawRoutingResult m_rawResult; Index const & m_index; RoutingMapping & m_routingMapping; @@ -562,7 +565,4 @@ IRouter::ResultCode OsrmRouter::FindPhantomNodes(m2::PointD const & point, getter.MakeResult(res, maxCount); return NoError; } - - - } // namespace routing diff --git a/routing/routing.pro b/routing/routing.pro index 5dc101412f..b5b9df45fe 100644 --- a/routing/routing.pro +++ b/routing/routing.pro @@ -21,13 +21,13 @@ SOURCES += \ cross_mwm_router.cpp \ cross_routing_context.cpp \ features_road_graph.cpp \ - loaded_path_segment.cpp \ nearest_edge_finder.cpp \ online_absent_fetcher.cpp \ online_cross_fetcher.cpp \ osrm2feature_map.cpp \ osrm_engine.cpp \ osrm_helpers.cpp \ + osrm_path_segment_factory.cpp \ osrm_router.cpp \ pedestrian_directions.cpp \ pedestrian_model.cpp \ @@ -66,6 +66,7 @@ HEADERS += \ osrm_data_facade.hpp \ osrm_engine.hpp \ osrm_helpers.hpp \ + osrm_path_segment_factory.hpp \ osrm_router.hpp \ pedestrian_directions.hpp \ pedestrian_model.hpp \ diff --git a/routing/routing_result_graph.hpp b/routing/routing_result_graph.hpp index 30465dc4c2..db06ce1c0b 100644 --- a/routing/routing_result_graph.hpp +++ b/routing/routing_result_graph.hpp @@ -17,7 +17,7 @@ namespace turns class IRoutingResultGraph { public: - virtual vector const & GetSegments() const = 0; + virtual vector> const & GetSegments() const = 0; virtual void GetPossibleTurns(TNodeId node, m2::PointD const & ingoingPoint, m2::PointD const & junctionPoint, size_t & ingoingCount, diff --git a/routing/turns_generator.cpp b/routing/turns_generator.cpp index 14f58d4304..65f9232442 100644 --- a/routing/turns_generator.cpp +++ b/routing/turns_generator.cpp @@ -283,11 +283,11 @@ IRouter::ResultCode MakeTurnAnnotation(turns::IRoutingResultGraph const & result ++loadedSegmentIt) { // ETA information. - double const nodeTimeSeconds = loadedSegmentIt->m_weight; + double const nodeTimeSeconds = (*loadedSegmentIt)->m_weight; // Street names. I put empty names too, to avoid freezing old street name while riding on // unnamed street. - streets.emplace_back(max(points.size(), static_cast(1)) - 1, loadedSegmentIt->m_name); + streets.emplace_back(max(points.size(), static_cast(1)) - 1, (*loadedSegmentIt)->m_name); // Turns information. if (!points.empty() && skipTurnSegments == 0) @@ -298,7 +298,7 @@ IRouter::ResultCode MakeTurnAnnotation(turns::IRoutingResultGraph const & result size_t segmentIndex = distance(loadedSegments.begin(), loadedSegmentIt); skipTurnSegments = CheckUTurnOnRoute(loadedSegments, segmentIndex, turnItem); - turns::TurnInfo turnInfo(loadedSegments[segmentIndex - 1], *loadedSegmentIt); + turns::TurnInfo turnInfo(*(loadedSegments[segmentIndex - 1]), **loadedSegmentIt); if (turnItem.m_turn == turns::TurnDirection::NoTurn) turns::GetTurnDirection(result, turnInfo, turnItem); @@ -327,7 +327,7 @@ IRouter::ResultCode MakeTurnAnnotation(turns::IRoutingResultGraph const & result --skipTurnSegments; // Path geometry. - points.insert(points.end(), loadedSegmentIt->m_path.begin(), loadedSegmentIt->m_path.end()); + points.insert(points.end(), (*loadedSegmentIt)->m_path.begin(), (*loadedSegmentIt)->m_path.end()); } // Path found. Points will be replaced by start and end edges points. @@ -662,7 +662,8 @@ void GetTurnDirection(IRoutingResultGraph const & result, TurnInfo & turnInfo, T } } -size_t CheckUTurnOnRoute(vector const & segments, size_t currentSegment, TurnItem & turn) +size_t CheckUTurnOnRoute(vector> const & segments, + size_t currentSegment, TurnItem & turn) { size_t constexpr kUTurnLookAhead = 3; double constexpr kUTurnHeadingSensitivity = math::pi / 10.0; @@ -672,7 +673,7 @@ size_t CheckUTurnOnRoute(vector const & segments, size_t curr ASSERT_GREATER(segments.size(), 1, ()); ASSERT_GREATER(currentSegment, 0, ()); ASSERT_GREATER(segments.size(), currentSegment, ()); - auto const & masterSegment = segments[currentSegment - 1]; + auto const & masterSegment = *(segments[currentSegment - 1]); if (masterSegment.m_path.size() < 2) return 0; // Roundabout is not the UTurn. @@ -680,7 +681,7 @@ size_t CheckUTurnOnRoute(vector const & segments, size_t curr return 0; for (size_t i = 0; i < kUTurnLookAhead && i + currentSegment < segments.size(); ++i) { - auto const & checkedSegment = segments[currentSegment + i]; + auto const & checkedSegment = *(segments[currentSegment + i]); if (checkedSegment.m_name == masterSegment.m_name && checkedSegment.m_highwayClass == masterSegment.m_highwayClass && checkedSegment.m_isLink == masterSegment.m_isLink && !checkedSegment.m_onRoundabout) @@ -722,7 +723,7 @@ size_t CheckUTurnOnRoute(vector const & segments, size_t curr m2::PointD const ingoingPoint = GetPointForTurn(masterSegment.m_path, junctionPoint, kMaxPointsCount, kMinDistMeters, GetIngoingPointIndex); - m2::PointD const outgoingPoint = GetPointForTurn(segments[currentSegment].m_path, junctionPoint, + m2::PointD const outgoingPoint = GetPointForTurn(segments[currentSegment]->m_path, junctionPoint, kMaxPointsCount, kMinDistMeters, GetOutgoingPointIndex); if (PiMinusTwoVectorsAngle(junctionPoint, ingoingPoint, outgoingPoint) < 0) diff --git a/routing/turns_generator.hpp b/routing/turns_generator.hpp index 7cb1eac483..9232658b19 100644 --- a/routing/turns_generator.hpp +++ b/routing/turns_generator.hpp @@ -10,6 +10,7 @@ #include "routing/turn_candidate.hpp" #include "std/function.hpp" +#include "std/unique_ptr.hpp" #include "std/utility.hpp" #include "std/vector.hpp" @@ -135,6 +136,7 @@ void GetTurnDirection(IRoutingResultGraph const & result, turns::TurnInfo & turn * Returns 0 if there is no UTurn. * Warning! currentSegment must be greater than 0. */ -size_t CheckUTurnOnRoute(vector const & segments, size_t currentSegment, TurnItem & turn); +size_t CheckUTurnOnRoute(vector> const & segments, + size_t currentSegment, TurnItem & turn); } // namespace routing } // namespace turns