diff --git a/map/mwm_tree.hpp b/map/mwm_tree.hpp index 8d4dd3b882..9a7f9084fe 100644 --- a/map/mwm_tree.hpp +++ b/map/mwm_tree.hpp @@ -3,6 +3,7 @@ #include "routing/num_mwm_id.hpp" #include "storage/country_info_getter.hpp" +#include "storage/storage.hpp" #include "geometry/tree4d.hpp" diff --git a/routing/bicycle_directions.cpp b/routing/bicycle_directions.cpp index 04091adcdd..7df13d9808 100644 --- a/routing/bicycle_directions.cpp +++ b/routing/bicycle_directions.cpp @@ -2,6 +2,7 @@ #include "routing/num_mwm_id.hpp" #include "routing/road_point.hpp" #include "routing/router_delegate.hpp" +#include "routing/routing_exceptions.hpp" #include "routing/routing_result_graph.hpp" #include "routing/turns.hpp" #include "routing/turns_generator.hpp" @@ -92,8 +93,11 @@ private: /// a part of LoadedPathSegment and returns true if the junction should be considered as a beginning /// of a new LoadedPathSegment. bool IsJoint(IRoadGraph::TEdgeVector const & ingoingEdges, - IRoadGraph::TEdgeVector const & outgoingEdges, Edge const & ingoingRouteEdge, - Edge const & outgoingRouteEdge) + IRoadGraph::TEdgeVector const & outgoingEdges, + Edge const & ingoingRouteEdge, + Edge const & outgoingRouteEdge, + bool isCurrJunctionFinish, + bool isInEdgeReal) { // When feature id is changed at a junction this junction should be considered as a joint. // @@ -109,6 +113,12 @@ bool IsJoint(IRoadGraph::TEdgeVector const & ingoingEdges, // | | // *--Seg0--*--Seg1--* // The common point of segments 0, 1 and 4 should be considered as a joint. + if (!isInEdgeReal) + return true; + + if (isCurrJunctionFinish) + return true; + if (ingoingRouteEdge.GetFeatureId() != outgoingRouteEdge.GetFeatureId()) return true; @@ -134,9 +144,11 @@ bool IsJoint(IRoadGraph::TEdgeVector const & ingoingEdges, namespace routing { BicycleDirectionsEngine::BicycleDirectionsEngine(Index const & index, - shared_ptr numMwmIds) - : m_index(index), m_numMwmIds(numMwmIds) + std::shared_ptr numMwmIds, + bool generateTrafficSegs) + : m_index(index), m_numMwmIds(numMwmIds), m_generateTrafficSegs(generateTrafficSegs) { + CHECK(m_numMwmIds, ()); } void BicycleDirectionsEngine::Generate(RoadGraphBase const & graph, vector const & path, @@ -235,10 +247,10 @@ void BicycleDirectionsEngine::GetUniNodeIdAndAdjacentEdges(IRoadGraph::TEdgeVect uint32_t startSegId, uint32_t endSegId, UniNodeId & uniNodeId, - BicycleDirectionsEngine::AdjacentEdges & adjacentEdges) + TurnCandidates & outgoingTurns) { - adjacentEdges.m_outgoingTurns.isCandidatesAngleValid = true; - adjacentEdges.m_outgoingTurns.candidates.reserve(outgoingEdges.size()); + outgoingTurns.isCandidatesAngleValid = true; + outgoingTurns.candidates.reserve(outgoingEdges.size()); uniNodeId = UniNodeId(inEdge.GetFeatureId(), startSegId, endSegId, inEdge.IsForward()); m2::PointD const & ingoingPoint = inEdge.GetStartJunction().GetPoint(); m2::PointD const & junctionPoint = inEdge.GetEndJunction().GetPoint(); @@ -273,25 +285,31 @@ void BicycleDirectionsEngine::GetUniNodeIdAndAdjacentEdges(IRoadGraph::TEdgeVect // twins of inEdge.GetFeatureId() are considered as outgoing features. // In this case that turn candidate angle is invalid and // should not be used for turn generation. - adjacentEdges.m_outgoingTurns.isCandidatesAngleValid = false; + outgoingTurns.isCandidatesAngleValid = false; } - adjacentEdges.m_outgoingTurns.candidates.emplace_back(angle, uniNodeId, highwayClass); + outgoingTurns.candidates.emplace_back(angle, uniNodeId, highwayClass); } } -bool BicycleDirectionsEngine::GetSegment(FeatureID const & featureId, uint32_t segId, - bool forward, Segment & segment) const +Segment BicycleDirectionsEngine::GetSegment(FeatureID const & featureId, uint32_t segId, bool forward) const { - if (!m_numMwmIds) - return false; + auto info = featureId.m_mwmId.GetInfo(); + if (!info) + MYTHROW(RoutingException, ("Mwm:", featureId.m_mwmId, "is not alive.")); - if (!featureId.m_mwmId.IsAlive()) - return false; + NumMwmId const numMwmId = m_numMwmIds->GetId(info->GetLocalFile().GetCountryFile()); + return Segment(numMwmId, featureId.m_index, segId, forward); +} - NumMwmId const numMwmId = - m_numMwmIds->GetId(featureId.m_mwmId.GetInfo()->GetLocalFile().GetCountryFile()); - segment = Segment(numMwmId, featureId.m_index, segId, forward); - return true; +void BicycleDirectionsEngine::GetEdges(RoadGraphBase const & graph, Junction const & currJunction, + bool isCurrJunctionFinish, IRoadGraph::TEdgeVector & outgoing, + IRoadGraph::TEdgeVector & ingoing) +{ + // Note. If |currJunction| is a finish the outgoing edges + // from finish are not important for turn generation. + if (!isCurrJunctionFinish) + graph.GetOutgoingEdges(currJunction, outgoing); + graph.GetIngoingEdges(currJunction, ingoing); } void BicycleDirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap( @@ -302,7 +320,6 @@ void BicycleDirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap( CHECK_GREATER(pathSize, 1, ()); CHECK_EQUAL(routeEdges.size(), pathSize - 1, ()); // Filling |m_adjacentEdges|. - m_adjacentEdges.insert(make_pair(UniNodeId(UniNodeId::Type::Mwm), AdjacentEdges(0))); auto constexpr kInvalidSegId = std::numeric_limits::max(); // |startSegId| is a value to keep start segment id of a new instance of LoadedPathSegment. uint32_t startSegId = kInvalidSegId; @@ -316,14 +333,10 @@ void BicycleDirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap( Junction const & prevJunction = path[i - 1]; Junction const & currJunction = path[i]; - // Note. i + 1 == pathSize means |currJunction| is a finish and the outgoing edges - // from finish are not important for turn generation. IRoadGraph::TEdgeVector outgoingEdges; - if (i + 1 != pathSize) - graph.GetOutgoingEdges(currJunction, outgoingEdges); - IRoadGraph::TEdgeVector ingoingEdges; - graph.GetIngoingEdges(currJunction, ingoingEdges); + bool const isCurrJunctionFinish = (i + 1 == pathSize); + GetEdges(graph, currJunction, isCurrJunctionFinish, outgoingEdges, ingoingEdges); Edge const & inEdge = routeEdges[i - 1]; // Note. |inFeatureId| may be invalid in case of adding fake features. @@ -335,26 +348,24 @@ void BicycleDirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap( if (startSegId == kInvalidSegId) startSegId = inSegId; - if (inFeatureId.IsValid() && i + 1 != pathSize && - !IsJoint(ingoingEdges, outgoingEdges, inEdge, routeEdges[i])) + prevJunctions.push_back(prevJunction); + if (m_generateTrafficSegs && !inEdge.IsFake()) + prevSegments.push_back(GetSegment(inFeatureId, inSegId, inIsForward)); + + if (!IsJoint(ingoingEdges, outgoingEdges, inEdge, routeEdges[i], isCurrJunctionFinish, + inFeatureId.IsValid())) { - prevJunctions.push_back(prevJunction); - Segment inSegment; - if (GetSegment(inFeatureId, inSegId, inIsForward, inSegment)) - prevSegments.push_back(inSegment); continue; } - CHECK_EQUAL(prevJunctions.size(), abs(static_cast(inSegId - startSegId)), ()); - prevJunctions.push_back(prevJunction); + CHECK_EQUAL(prevJunctions.size(), abs(static_cast(inSegId - startSegId)) + 1, ()); + prevJunctions.push_back(currJunction); - Segment segment; - if (GetSegment(inFeatureId, inSegId, inIsForward, segment)) - prevSegments.push_back(segment); AdjacentEdges adjacentEdges(ingoingEdges.size()); UniNodeId uniNodeId(UniNodeId::Type::Mwm); - GetUniNodeIdAndAdjacentEdges(outgoingEdges, inEdge, startSegId, inSegId + 1, uniNodeId, adjacentEdges); + GetUniNodeIdAndAdjacentEdges(outgoingEdges, inEdge, startSegId, inSegId + 1, uniNodeId, + adjacentEdges.m_outgoingTurns); size_t const prevJunctionSize = prevJunctions.size(); LoadedPathSegment pathSegment(UniNodeId::Type::Mwm); @@ -370,7 +381,7 @@ void BicycleDirectionsEngine::FillPathSegmentsAndAdjacentEdgesMap( // It leads to preventing pushing item to |prevSegments|. So if there's no enough items in |prevSegments| // |pathSegment.m_trafficSegs| should be empty. // Note. For the time being BicycleDirectionsEngine is used for turn generation for bicycle and car routes. - if (prevSegments.size() + 1 == prevJunctionSize) + if (m_generateTrafficSegs && prevSegments.size() + 1 == prevJunctionSize) pathSegment.m_trafficSegs = std::move(prevSegments); auto const it = m_adjacentEdges.insert(make_pair(uniNodeId, std::move(adjacentEdges))); diff --git a/routing/bicycle_directions.hpp b/routing/bicycle_directions.hpp index 6d5ef79dd4..8c28866274 100644 --- a/routing/bicycle_directions.hpp +++ b/routing/bicycle_directions.hpp @@ -24,7 +24,9 @@ public: using AdjacentEdgesMap = std::map; - BicycleDirectionsEngine(Index const & index, std::shared_ptr numMwmIds); + BicycleDirectionsEngine(Index const & index, + std::shared_ptr numMwmIds, + bool generateTrafficSegs); // IDirectionsEngine override: void Generate(RoadGraphBase const & graph, vector const & path, @@ -39,7 +41,7 @@ private: uint32_t startSegId, uint32_t endSegId, UniNodeId & uniNodeId, - BicycleDirectionsEngine::AdjacentEdges & adjacentEdges); + turns::TurnCandidates & outgoingTurns); /// \brief The method gathers sequence of segments according to IsJoint() method /// and fills |m_adjacentEdges| and |m_pathSegments|. void FillPathSegmentsAndAdjacentEdgesMap(RoadGraphBase const & graph, @@ -47,13 +49,19 @@ private: IRoadGraph::TEdgeVector const & routeEdges, my::Cancellable const & cancellable); - bool GetSegment(FeatureID const & featureId, uint32_t segId, bool forward, - Segment & segment) const; + Segment GetSegment(FeatureID const & featureId, uint32_t segId, bool forward) const; + + void GetEdges(RoadGraphBase const & graph, Junction const & currJunction, + bool isCurrJunctionFinish, IRoadGraph::TEdgeVector & outgoing, + IRoadGraph::TEdgeVector & ingoing); AdjacentEdgesMap m_adjacentEdges; TUnpackedPathSegments m_pathSegments; Index const & m_index; std::shared_ptr m_numMwmIds; std::unique_ptr m_loader; + // If |m_generateTrafficSegs| is set to true |LoadedPathSegment::m_trafficSeg| is filled + // and not otherwise. + bool const m_generateTrafficSegs; }; } // namespace routing diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 0329658494..6471566246 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -405,7 +405,7 @@ unique_ptr IndexRouter::CreateCarRouter(TCountryFileFn const & coun auto vehicleModelFactory = make_shared(); // @TODO Bicycle turn generation engine is used now. It's ok for the time being. // But later a special car turn generation engine should be implemented. - auto directionsEngine = make_unique(index, numMwmIds); + auto directionsEngine = make_unique(index, numMwmIds, true /* generateTrafficSegs */); double maxSpeed = 0.0; numMwmIds->ForEachId([&](NumMwmId id) { diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 97f7ae2bc2..ccff0819ae 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -234,7 +234,9 @@ unique_ptr CreatePedestrianAStarRouter(Index & index, TCountryFileFn co return router; } -unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn) +unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, + TCountryFileFn const & countryFileFn, + shared_ptr /* numMwmIds */) { unique_ptr vehicleModelFactory(new PedestrianModelFactory()); unique_ptr algorithm(new AStarBidirectionalRoutingAlgorithm()); @@ -245,11 +247,14 @@ unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, TCou return router; } -unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn) +unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, + TCountryFileFn const & countryFileFn, + shared_ptr numMwmIds) { unique_ptr vehicleModelFactory(new BicycleModelFactory()); unique_ptr algorithm(new AStarBidirectionalRoutingAlgorithm()); - unique_ptr directionsEngine(new BicycleDirectionsEngine(index, nullptr)); + unique_ptr directionsEngine( + new BicycleDirectionsEngine(index, numMwmIds, false /* generateTrafficSegs */)); unique_ptr router(new RoadGraphRouter( "astar-bidirectional-bicycle", index, countryFileFn, IRoadGraph::Mode::ObeyOnewayTag, move(vehicleModelFactory), move(algorithm), move(directionsEngine))); diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index a5e632aa4f..843d7a097c 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -10,6 +10,7 @@ #include "indexer/mwm_set.hpp" #include "geometry/point2d.hpp" +#include "geometry/tree4d.hpp" #include "std/function.hpp" #include "std/string.hpp" @@ -51,6 +52,10 @@ private: }; unique_ptr CreatePedestrianAStarRouter(Index & index, TCountryFileFn const & countryFileFn); -unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn); -unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, TCountryFileFn const & countryFileFn); +unique_ptr CreatePedestrianAStarBidirectionalRouter(Index & index, + TCountryFileFn const & countryFileFn, + shared_ptr /* numMwmIds */); +unique_ptr CreateBicycleAStarBidirectionalRouter(Index & index, + TCountryFileFn const & countryFileFn, + shared_ptr numMwmIds); } // namespace routing diff --git a/routing/routing_benchmarks/bicycle_routing_tests.cpp b/routing/routing_benchmarks/bicycle_routing_tests.cpp index 39b513cbdd..5c1f62cc52 100644 --- a/routing/routing_benchmarks/bicycle_routing_tests.cpp +++ b/routing/routing_benchmarks/bicycle_routing_tests.cpp @@ -25,10 +25,11 @@ public: protected: // RoutingTest overrides: - unique_ptr CreateDirectionsEngine() override + unique_ptr CreateDirectionsEngine( + shared_ptr numMwmIds) override { - unique_ptr engine( - new routing::BicycleDirectionsEngine(m_index, nullptr /* numMwmIds */)); + unique_ptr engine(new routing::BicycleDirectionsEngine( + m_index, numMwmIds, false /* generateTrafficSegs */)); return engine; } diff --git a/routing/routing_benchmarks/helpers.cpp b/routing/routing_benchmarks/helpers.cpp index 139a3d7e09..9c36a5223f 100644 --- a/routing/routing_benchmarks/helpers.cpp +++ b/routing/routing_benchmarks/helpers.cpp @@ -70,6 +70,8 @@ RoutingTest::RoutingTest(routing::IRoadGraph::Mode mode, set const & nee set registeredMaps; for (auto const & localFile : localFiles) { + m_numMwmIds->RegisterFile(localFile.GetCountryFile()); + auto const & name = localFile.GetCountryName(); if (neededMaps.count(name) == 0) continue; diff --git a/routing/routing_benchmarks/helpers.hpp b/routing/routing_benchmarks/helpers.hpp index f72309e1d6..b449dd5915 100644 --- a/routing/routing_benchmarks/helpers.hpp +++ b/routing/routing_benchmarks/helpers.hpp @@ -1,5 +1,6 @@ #pragma once +#include "routing/num_mwm_id.hpp" #include "routing/road_graph.hpp" #include "routing/router.hpp" #include "routing/road_graph_router.hpp" @@ -30,7 +31,8 @@ public: void TestTwoPointsOnFeature(m2::PointD const & startPos, m2::PointD const & finalPos); protected: - virtual unique_ptr CreateDirectionsEngine() = 0; + virtual unique_ptr CreateDirectionsEngine( + shared_ptr numMwmIds) = 0; virtual unique_ptr CreateModelFactory() = 0; template @@ -40,7 +42,7 @@ protected: unique_ptr algorithm(new Algorithm()); unique_ptr router( new routing::RoadGraphRouter(name, m_index, getter, m_mode, CreateModelFactory(), - move(algorithm), CreateDirectionsEngine())); + move(algorithm), CreateDirectionsEngine(m_numMwmIds))); return router; } @@ -49,6 +51,8 @@ protected: routing::IRoadGraph::Mode const m_mode; Index m_index; + + shared_ptr m_numMwmIds; unique_ptr m_cig; }; diff --git a/routing/routing_benchmarks/pedestrian_routing_tests.cpp b/routing/routing_benchmarks/pedestrian_routing_tests.cpp index c0120a4198..45510c019e 100644 --- a/routing/routing_benchmarks/pedestrian_routing_tests.cpp +++ b/routing/routing_benchmarks/pedestrian_routing_tests.cpp @@ -38,7 +38,8 @@ public: protected: // RoutingTest overrides: - unique_ptr CreateDirectionsEngine() override + unique_ptr CreateDirectionsEngine( + shared_ptr /* numMwmIds */) override { unique_ptr engine(new routing::PedestrianDirectionsEngine()); return engine; diff --git a/routing/routing_helpers.cpp b/routing/routing_helpers.cpp index 8491b7f319..c1fb78e68e 100644 --- a/routing/routing_helpers.cpp +++ b/routing/routing_helpers.cpp @@ -80,7 +80,6 @@ void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, } traffic.push_back(segTraffic); } - CHECK(!traffic.empty(), ()); CHECK_EQUAL(trafficSegs.size(), traffic.size(), ()); } diff --git a/routing/routing_integration_tests/get_altitude_test.cpp b/routing/routing_integration_tests/get_altitude_test.cpp index 57209cf740..663fa87656 100644 --- a/routing/routing_integration_tests/get_altitude_test.cpp +++ b/routing/routing_integration_tests/get_altitude_test.cpp @@ -28,7 +28,7 @@ void TestAltitudeOfAllMwmFeatures(string const & countryId, TAltitude const alti TAltitude const altitudeUpperBoundMeters) { Index index; - platform::LocalCountryFile const country = platform::LocalCountryFile::MakeForTesting(countryId, 170511); + platform::LocalCountryFile const country = platform::LocalCountryFile::MakeForTesting(countryId); pair const regResult = index.RegisterMap(country); TEST_EQUAL(regResult.second, MwmSet::RegResult::Success, ()); diff --git a/routing/routing_integration_tests/routing_test_tools.cpp b/routing/routing_integration_tests/routing_test_tools.cpp index fcf58d5c8d..96be947e8a 100644 --- a/routing/routing_integration_tests/routing_test_tools.cpp +++ b/routing/routing_integration_tests/routing_test_tools.cpp @@ -36,7 +36,8 @@ using namespace routing; using namespace routing_test; using TRouterFactory = - function(Index & index, TCountryFileFn const & countryFileFn)>; + function(Index & index, TCountryFileFn const & countryFileFn, + shared_ptr numMwmIds)>; namespace { @@ -109,6 +110,7 @@ namespace integration unique_ptr CreateAStarRouter(Index & index, storage::CountryInfoGetter const & infoGetter, + vector const & localFiles, TRouterFactory const & routerFactory) { // |infoGetter| should be a reference to an object which exists while the @@ -117,7 +119,12 @@ namespace integration { return infoGetter.GetRegionCountryId(pt); }; - unique_ptr router = routerFactory(index, countryFileGetter); + + auto numMwmIds = make_shared(); + for (auto const & file : localFiles) + numMwmIds->RegisterFile(file.GetCountryFile()); + + unique_ptr router = routerFactory(index, countryFileGetter, numMwmIds); return unique_ptr(move(router)); } @@ -143,7 +150,7 @@ namespace integration public: PedestrianRouterComponents(vector const & localFiles) : IRouterComponents(localFiles) - , m_router(CreateAStarRouter(m_featuresFetcher->GetIndex(), *m_infoGetter, + , m_router(CreateAStarRouter(m_featuresFetcher->GetIndex(), *m_infoGetter, localFiles, CreatePedestrianAStarBidirectionalRouter)) { } @@ -159,7 +166,7 @@ namespace integration public: BicycleRouterComponents(vector const & localFiles) : IRouterComponents(localFiles) - , m_router(CreateAStarRouter(m_featuresFetcher->GetIndex(), *m_infoGetter, + , m_router(CreateAStarRouter(m_featuresFetcher->GetIndex(), *m_infoGetter, localFiles, CreateBicycleAStarBidirectionalRouter)) { } diff --git a/routing/turns.cpp b/routing/turns.cpp index 0d63c22010..b536df27a7 100644 --- a/routing/turns.cpp +++ b/routing/turns.cpp @@ -52,7 +52,7 @@ static_assert(g_turnNames.size() == static_cast(TurnDirection::Count), namespace routing { // UniNodeId ------------------------------------------------------------------- -std::atomic UniNodeId::m_nextFakeId(0); +std::atomic UniNodeId::m_nextFakeId(0); UniNodeId::UniNodeId(FeatureID const & featureId, uint32_t startSegId, uint32_t endSegId, bool forward) @@ -63,7 +63,10 @@ UniNodeId::UniNodeId(FeatureID const & featureId, uint32_t startSegId, uint32_t , m_forward(forward) { if (!m_featureId.IsValid()) + { m_nodeId = m_nextFakeId++; + CHECK_NOT_EQUAL(m_nodeId, SPECIAL_NODEID, ()); + } } bool UniNodeId::operator==(UniNodeId const & rhs) const diff --git a/routing/turns.hpp b/routing/turns.hpp index 781b659a3f..f169eaf7db 100644 --- a/routing/turns.hpp +++ b/routing/turns.hpp @@ -39,7 +39,7 @@ struct UniNodeId FeatureID const & GetFeature() const; private: - static std::atomic m_nextFakeId; + static std::atomic m_nextFakeId; Type m_type; FeatureID m_featureId; // Not valid for OSRM. diff --git a/routing/turns_generator.cpp b/routing/turns_generator.cpp index 01bc6ca9f4..f2dd433642 100644 --- a/routing/turns_generator.cpp +++ b/routing/turns_generator.cpp @@ -326,6 +326,13 @@ IRouter::ResultCode MakeTurnAnnotation(turns::IRoutingResult const & result, // Path geometry. CHECK_GREATER_OR_EQUAL(loadedSegmentIt->m_path.size(), 2, ()); + // Note. Every LoadedPathSegment in TUnpackedPathSegments contains LoadedPathSegment::m_path + // of several Junctions. Last Junction in a LoadedPathSegment::m_path is equal to first junction + // in next LoadedPathSegment::m_path in vector TUnpackedPathSegments: + // *---*---*---*---* *---* *---*---*---* + // *---*---* *---*---*---* + // To prevent having repetitions in |junctions| list it's necessary to take the first point only from the + // first item of |loadedSegments|. The beginning should be ignored for the rest |m_path|. junctions.insert(junctions.end(), loadedSegmentIt == loadedSegments.cbegin() ? loadedSegmentIt->m_path.cbegin() : loadedSegmentIt->m_path.cbegin() + 1,