diff --git a/generator/routing_index_generator.cpp b/generator/routing_index_generator.cpp index f4e01e0ca9..1e293e2f39 100644 --- a/generator/routing_index_generator.cpp +++ b/generator/routing_index_generator.cpp @@ -289,7 +289,6 @@ void FillWeights(string const & path, string const & mwmFile, string const & cou DeserializeIndexGraph(mwmValue, graph); map> weights; - map distanceMap; auto const numEnters = connector.GetEnters().size(); size_t foundCount = 0; size_t notFoundCount = 0; @@ -302,18 +301,16 @@ void FillWeights(string const & path, string const & mwmFile, string const & cou AStarAlgorithm astar; DijkstraWrapper wrapper(graph); - astar.PropagateWave( - wrapper, enter, [](Segment const & /* vertex */) { return false; }, - [](Segment const & /* vertex */, SegmentEdge const & edge) { return edge.GetWeight(); }, - [](Segment const & /* from */, Segment const & /* to */) {} /* putToParents */, - distanceMap); + AStarAlgorithm::Context context; + astar.PropagateWave(wrapper, enter, + [](Segment const & /* vertex */) { return true; } /* visitVertex */, + context); for (Segment const & exit : connector.GetExits()) { - auto it = distanceMap.find(exit); - if (it != distanceMap.end()) + if (context.HasDistance(exit)) { - weights[enter][exit] = it->second; + weights[enter][exit] = context.GetDistance(exit); ++foundCount; } else diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 8a8ab0db49..23b88f8b32 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -565,8 +565,9 @@ void RoutingManager::CheckLocationForRouting(location::GpsInfo const & info) { m_routingSession.RebuildRoute( MercatorBounds::FromLatLon(info.m_latitude, info.m_longitude), - [&](Route const & route, IRouter::ResultCode code) { OnRebuildRouteReady(route, code); }, - 0 /* timeoutSec */, routing::RoutingSession::State::RouteRebuilding); + [this](Route const & route, IRouter::ResultCode code) { OnRebuildRouteReady(route, code); }, + 0 /* timeoutSec */, routing::RoutingSession::State::RouteRebuilding, + true /* adjustToPrevRoute */); } } diff --git a/routing/async_router.cpp b/routing/async_router.cpp index 140bb8c044..3a7bb737b3 100644 --- a/routing/async_router.cpp +++ b/routing/async_router.cpp @@ -147,7 +147,7 @@ void AsyncRouter::SetRouter(unique_ptr && router, unique_ptr delegate; m2::PointD startPoint, finalPoint, startDirection; - bool adjust = false; + bool adjustToPrevRoute = false; shared_ptr absentFetcher; shared_ptr router; @@ -278,7 +278,7 @@ void AsyncRouter::CalculateRoute() startPoint = m_startPoint; finalPoint = m_finalPoint; startDirection = m_startDirection; - adjust = m_adjust; + adjustToPrevRoute = m_adjustToPrevRoute; delegate = m_delegate; router = m_router; absentFetcher = m_absentFetcher; @@ -298,7 +298,7 @@ void AsyncRouter::CalculateRoute() absentFetcher->GenerateRequest(startPoint, finalPoint); // Run basic request. - code = router->CalculateRoute(startPoint, startDirection, finalPoint, adjust, + code = router->CalculateRoute(startPoint, startDirection, finalPoint, adjustToPrevRoute, delegate->GetDelegate(), route); elapsedSec = timer.ElapsedSeconds(); // routing time diff --git a/routing/async_router.hpp b/routing/async_router.hpp index 21698ed376..769db545bf 100644 --- a/routing/async_router.hpp +++ b/routing/async_router.hpp @@ -43,12 +43,12 @@ public: /// @param startPoint point to start routing /// @param direction start direction for routers with high cost of the turnarounds /// @param finalPoint target point for route - /// @param adjust adjust route to the previous one if possible + /// @param adjustToPrevRoute adjust route to the previous one if possible /// @param readyCallback function to return routing result /// @param progressCallback function to update the router progress /// @param timeoutSec timeout to cancel routing. 0 is infinity. void CalculateRoute(m2::PointD const & startPoint, m2::PointD const & direction, - m2::PointD const & finalPoint, bool adjust, + m2::PointD const & finalPoint, bool adjustToPrevRoute, TReadyCallback const & readyCallback, RouterDelegate::TProgressCallback const & progressCallback, uint32_t timeoutSec); @@ -112,11 +112,11 @@ private: bool m_hasRequest; /// Current request parameters - bool m_clearState; - m2::PointD m_startPoint; - m2::PointD m_finalPoint; - m2::PointD m_startDirection; - bool m_adjust = false; + bool m_clearState = false; + m2::PointD m_startPoint = m2::PointD::Zero(); + m2::PointD m_finalPoint = m2::PointD::Zero(); + m2::PointD m_startDirection = m2::PointD::Zero(); + bool m_adjustToPrevRoute = false; shared_ptr m_delegate; shared_ptr m_absentFetcher; shared_ptr m_router; diff --git a/routing/base/astar_algorithm.hpp b/routing/base/astar_algorithm.hpp index d7f8964011..ebd27b4085 100644 --- a/routing/base/astar_algorithm.hpp +++ b/routing/base/astar_algorithm.hpp @@ -5,6 +5,7 @@ #include "std/algorithm.hpp" #include "std/functional.hpp" #include "std/iostream.hpp" +#include "std/limits.hpp" #include "std/map.hpp" #include "std/queue.hpp" #include "std/vector.hpp" @@ -61,17 +62,56 @@ public: using TOnVisitedVertexCallback = std::function; - template - void PropagateWave(TGraphType & graph, TVertexType const & startVertex, - CheckForStop && checkForStop, AdjustEdgeWeight && adjustEdgeWeight, - PutToParents && putToParents, map & bestDistance) const; + class Context final + { + public: + void Clear() + { + m_distanceMap.clear(); + m_parents.clear(); + } - template - Result FindPath(TGraphType & graph, TVertexType const & startVertex, - TVertexType const & finalVertex, RoutingResult & result, - my::Cancellable const & cancellable, - TOnVisitedVertexCallback onVisitedVertexCallback, - IsFinalVertex && isFinalVertex) const; + bool HasDistance(TVertexType const & vertex) const + { + return m_distanceMap.find(vertex) != m_distanceMap.cend(); + } + + double GetDistance(TVertexType const & vertex) const + { + auto const & it = m_distanceMap.find(vertex); + if (it == m_distanceMap.cend()) + return kInfiniteDistance; + + return it->second; + } + + void SetDistance(TVertexType const & vertex, double distance) + { + m_distanceMap[vertex] = distance; + } + + void SetParent(TVertexType const & parent, TVertexType const & child) + { + m_parents[parent] = child; + } + + void ReconstructPath(TVertexType const & v, vector & path) const; + + private: + map m_distanceMap; + map m_parents; + }; + + // VisitVertex returns true: wave will continue + // VisitVertex returns false: wave will stop + template + void PropagateWave(TGraphType & graph, TVertexType const & startVertex, + VisitVertex && visitVertex, AdjustEdgeWeight && adjustEdgeWeight, + Context & context) const; + + template + void PropagateWave(TGraphType & graph, TVertexType const & startVertex, + VisitVertex && visitVertex, Context & context) const; Result FindPath(TGraphType & graph, TVertexType const & startVertex, TVertexType const & finalVertex, RoutingResult & result, @@ -84,18 +124,37 @@ public: my::Cancellable const & cancellable = my::Cancellable(), TOnVisitedVertexCallback onVisitedVertexCallback = nullptr) const; + // Adjust route to the previous one. + // adjustLimit - distance limit for wave propagation, measured in same units as graph edges length. + typename AStarAlgorithm::Result AdjustRoute( + TGraphType & graph, TVertexType const & startVertex, vector const & prevRoute, + double adjustLimit, RoutingResult & result, my::Cancellable const & cancellable, + TOnVisitedVertexCallback onVisitedVertexCallback) const; + private: - // Periodicy of checking is cancellable cancelled. - static uint32_t constexpr kCancelledPollPeriod = 128; - - // Periodicy of switching a wave of bidirectional algorithm. + // Periodicity of switching a wave of bidirectional algorithm. static uint32_t constexpr kQueueSwitchPeriod = 128; - // Periodicy of calling callback about visited vertice. - static uint32_t constexpr kVisitedVerticesPeriod = 4; - // Precision of comparison weights. static double constexpr kEpsilon = 1e-6; + static double constexpr kInfiniteDistance = numeric_limits::max(); + + class PeriodicPollCancellable final + { + public: + PeriodicPollCancellable(my::Cancellable const & cancellable) : m_cancellable(cancellable) {} + + bool IsCancelled() + { + // Periodicity of checking is cancellable cancelled. + uint32_t constexpr kPeriod = 128; + return count++ % kPeriod == 0 && m_cancellable.IsCancelled(); + } + + private: + my::Cancellable const & m_cancellable; + uint32_t count = 0; + }; // State is what is going to be put in the priority queue. See the // comment for FindPath for more information. @@ -183,18 +242,17 @@ private: }; template -template +template void AStarAlgorithm::PropagateWave(TGraphType & graph, TVertexType const & startVertex, - CheckForStop && checkForStop, + VisitVertex && visitVertex, AdjustEdgeWeight && adjustEdgeWeight, - PutToParents && putToParents, - map & bestDistance) const + AStarAlgorithm::Context & context) const { - bestDistance.clear(); + context.Clear(); priority_queue, greater> queue; - bestDistance[startVertex] = 0.0; + context.SetDistance(startVertex, 0.0); queue.push(State(startVertex, 0.0)); vector adj; @@ -204,10 +262,10 @@ void AStarAlgorithm::PropagateWave(TGraphType & graph, TVertexType const State const stateV = queue.top(); queue.pop(); - if (stateV.distance > bestDistance[stateV.vertex]) + if (stateV.distance > context.GetDistance(stateV.vertex)) continue; - if (checkForStop(stateV.vertex)) + if (!visitVertex(stateV.vertex)) return; graph.GetOutgoingEdgesList(stateV.vertex, adj); @@ -220,18 +278,29 @@ void AStarAlgorithm::PropagateWave(TGraphType & graph, TVertexType const double const edgeWeight = adjustEdgeWeight(stateV.vertex, edge); double const newReducedDist = stateV.distance + edgeWeight; - auto const t = bestDistance.find(stateW.vertex); - if (t != bestDistance.end() && newReducedDist >= t->second - kEpsilon) + if (newReducedDist >= context.GetDistance(stateW.vertex) - kEpsilon) continue; stateW.distance = newReducedDist; - bestDistance[stateW.vertex] = newReducedDist; - putToParents(stateW.vertex, stateV.vertex); + context.SetDistance(stateW.vertex, newReducedDist); + context.SetParent(stateW.vertex, stateV.vertex); queue.push(stateW); } } } +template +template +void AStarAlgorithm::PropagateWave(TGraphType & graph, TVertexType const & startVertex, + VisitVertex && visitVertex, + AStarAlgorithm::Context & context) const +{ + auto const adjustEdgeWeight = [](TVertexType const & /* vertex */, TEdgeType const & edge) { + return edge.GetWeight(); + }; + PropagateWave(graph, startVertex, visitVertex, adjustEdgeWeight, context); +} + // This implementation is based on the view that the A* algorithm // is equivalent to Dijkstra's algorithm that is run on a reweighted // version of the graph. If an edge (v, w) has length l(v, w), its reduced @@ -244,43 +313,35 @@ void AStarAlgorithm::PropagateWave(TGraphType & graph, TVertexType const // http://www.cs.princeton.edu/courses/archive/spr06/cos423/Handouts/EPP%20shortest%20path%20algorithms.pdf template -template typename AStarAlgorithm::Result AStarAlgorithm::FindPath( TGraphType & graph, TVertexType const & startVertex, TVertexType const & finalVertex, RoutingResult & result, my::Cancellable const & cancellable, - TOnVisitedVertexCallback onVisitedVertexCallback, IsFinalVertex && isFinalVertex) const + TOnVisitedVertexCallback onVisitedVertexCallback) const { result.Clear(); if (nullptr == onVisitedVertexCallback) onVisitedVertexCallback = [](TVertexType const &, TVertexType const &) {}; - map bestDistance; - map parents; - uint32_t steps = 0; + Context context; + PeriodicPollCancellable periodicCancellable(cancellable); Result resultCode = Result::NoPath; - auto checkForStop = [&](TVertexType const & vertex) { - ++steps; - - if (steps % kCancelledPollPeriod == 0 && cancellable.IsCancelled()) + auto visitVertex = [&](TVertexType const & vertex) { + if (periodicCancellable.IsCancelled()) { resultCode = Result::Cancelled; - return true; + return false; } - if (steps % kVisitedVerticesPeriod == 0) - onVisitedVertexCallback(vertex, finalVertex); + onVisitedVertexCallback(vertex, finalVertex); - if (isFinalVertex(vertex)) + if (vertex == finalVertex) { - ReconstructPath(vertex, parents, result.path); - result.distance = bestDistance[vertex] - graph.HeuristicCostEstimate(vertex, finalVertex) + - graph.HeuristicCostEstimate(startVertex, finalVertex); resultCode = Result::OK; - return true; + return false; } - return false; + return true; }; auto adjustEdgeWeight = [&](TVertexType const & vertex, TEdgeType const & edge) { @@ -293,23 +354,18 @@ typename AStarAlgorithm::Result AStarAlgorithm::FindPath( return max(reducedLen, 0.0); }; - auto putToParents = [&](TVertexType const & from, TVertexType const & to) { parents[from] = to; }; + PropagateWave(graph, startVertex, visitVertex, adjustEdgeWeight, context); + + if (resultCode == Result::OK) + { + context.ReconstructPath(finalVertex, result.path); + result.distance = + context.GetDistance(finalVertex) - graph.HeuristicCostEstimate(startVertex, finalVertex); + } - PropagateWave(graph, startVertex, checkForStop, adjustEdgeWeight, putToParents, bestDistance); return resultCode; } -template -typename AStarAlgorithm::Result AStarAlgorithm::FindPath( - TGraphType & graph, TVertexType const & startVertex, TVertexType const & finalVertex, - RoutingResult & result, my::Cancellable const & cancellable, - TOnVisitedVertexCallback onVisitedVertexCallback) const -{ - auto const isFinalVertex = [&](TVertexType const & vertex) { return vertex == finalVertex; }; - return FindPath(graph, startVertex, finalVertex, result, cancellable, onVisitedVertexCallback, - isFinalVertex); -} - template typename AStarAlgorithm::Result AStarAlgorithm::FindPathBidirectional( TGraphType & graph, @@ -347,11 +403,13 @@ typename AStarAlgorithm::Result AStarAlgorithm::FindPathBidirect // because if we have not found a path by the time one of the // queues is exhausted, we never will. uint32_t steps = 0; + PeriodicPollCancellable periodicCancellable(cancellable); + while (!cur->queue.empty() && !nxt->queue.empty()) { ++steps; - if (steps % kCancelledPollPeriod == 0 && cancellable.IsCancelled()) + if (periodicCancellable.IsCancelled()) return Result::Cancelled; if (steps % kQueueSwitchPeriod == 0) @@ -391,8 +449,7 @@ typename AStarAlgorithm::Result AStarAlgorithm::FindPathBidirect if (stateV.distance > cur->bestDistance[stateV.vertex]) continue; - if (steps % kVisitedVerticesPeriod == 0) - onVisitedVertexCallback(stateV.vertex, cur->forward ? cur->finalVertex : cur->startVertex); + onVisitedVertexCallback(stateV.vertex, cur->forward ? cur->finalVertex : cur->startVertex); cur->GetAdjacencyList(stateV.vertex, adj); for (auto const & edge : adj) @@ -445,6 +502,94 @@ typename AStarAlgorithm::Result AStarAlgorithm::FindPathBidirect return Result::NoPath; } +template +typename AStarAlgorithm::Result AStarAlgorithm::AdjustRoute( + TGraphType & graph, TVertexType const & startVertex, vector const & prevRoute, + double adjustLimit, RoutingResult & result, my::Cancellable const & cancellable, + TOnVisitedVertexCallback onVisitedVertexCallback) const +{ + CHECK(!prevRoute.empty(), ()); + + result.Clear(); + if (onVisitedVertexCallback == nullptr) + onVisitedVertexCallback = [](TVertexType const &, TVertexType const &) {}; + + bool wasCancelled = false; + double minDistance = kInfiniteDistance; + TVertexType returnVertex; + + map remainingDistances; + double remainingDistance = 0.0; + + for (auto it = prevRoute.crbegin(); it != prevRoute.crend(); ++it) + { + remainingDistances[it->GetTarget()] = remainingDistance; + remainingDistance += it->GetWeight(); + } + + Context context; + PeriodicPollCancellable periodicCancellable(cancellable); + + auto visitVertex = [&](TVertexType const & vertex) { + + if (periodicCancellable.IsCancelled()) + { + wasCancelled = true; + return false; + } + + auto const distance = context.GetDistance(vertex); + if (distance > adjustLimit) + return false; + + onVisitedVertexCallback(startVertex, vertex); + + auto it = remainingDistances.find(vertex); + if (it != remainingDistances.cend()) + { + double const fullDistance = distance + it->second; + if (fullDistance < minDistance) + { + minDistance = fullDistance; + returnVertex = vertex; + } + } + + return true; + }; + + PropagateWave(graph, startVertex, visitVertex, context); + if (wasCancelled) + return Result::Cancelled; + + if (minDistance == kInfiniteDistance) + return Result::NoPath; + + context.ReconstructPath(returnVertex, result.path); + + // Append remaining route. + bool found = false; + for (size_t i = 0; i < prevRoute.size(); ++i) + { + if (prevRoute[i].GetTarget() == returnVertex) + { + for (size_t j = i + 1; j < prevRoute.size(); ++j) + result.path.push_back(prevRoute[j].GetTarget()); + + found = true; + break; + } + } + + CHECK(found, + ("Can't find", returnVertex, ", prev:", prevRoute.size(), ", adjust:", result.path.size())); + + auto const & it = remainingDistances.find(returnVertex); + CHECK(it != remainingDistances.end(), ()); + result.distance = context.GetDistance(returnVertex) + it->second; + return Result::OK; +} + // static template void AStarAlgorithm::ReconstructPath(TVertexType const & v, @@ -480,4 +625,10 @@ void AStarAlgorithm::ReconstructPathBidirectional( path.insert(path.end(), pathW.rbegin(), pathW.rend()); } +template +void AStarAlgorithm::Context::ReconstructPath(TVertexType const & v, + vector & path) const +{ + AStarAlgorithm::ReconstructPath(v, m_parents, path); +} } // namespace routing diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 9212eedd13..88d55ca211 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -29,21 +29,23 @@ #include "base/exception.hpp" #include +#include using namespace routing; +using namespace std; namespace { size_t constexpr kMaxRoadCandidates = 6; float constexpr kProgressInterval = 2; -uint32_t constexpr kDrawPointsPeriod = 10; +uint32_t constexpr kVisitPeriod = 40; -// If user left the route within this range, adjust the route. Else full rebuild. -double constexpr kAdjustRange = 5000.0; -// Propagate astar wave for some distance to try to find a better return point. -double constexpr kAdjustDistance = 2000.0; -// Full rebuild if distance to finish is lesser. -double const kMinDistanceToFinish = kAdjustDistance * 2.0; +// If user left the route within this range(meters), adjust the route. Else full rebuild. +double constexpr kAdjustRangeM = 5000.0; +// Full rebuild if distance(meters) is less. +double constexpr kMinDistanceToFinishM = 10000; +// Limit of adjust in seconds. +double constexpr kAdjustLimitSec = 5 * 60; template IRouter::ResultCode ConvertResult(typename AStarAlgorithm::Result result) @@ -65,7 +67,7 @@ IRouter::ResultCode FindPath( { AStarAlgorithm algorithm; return ConvertResult(algorithm.FindPathBidirectional(graph, start, finish, routingResult, - delegate, onVisitedVertexCallback)); + delegate, onVisitedVertexCallback)); } bool IsDeadEnd(Segment const & segment, bool isOutgoing, WorldGraph & worldGraph) @@ -142,7 +144,8 @@ IndexRouter::IndexRouter(string const & name, TCountryFileFn const & countryFile IRouter::ResultCode IndexRouter::CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, bool adjust, + m2::PointD const & finalPoint, + bool adjustToPrevRoute, RouterDelegate const & delegate, Route & route) { if (!AllMwmsHaveRoutingIndex(m_index, route)) @@ -151,37 +154,35 @@ IRouter::ResultCode IndexRouter::CalculateRoute(m2::PointD const & startPoint, string const startCountry = m_countryFileFn(startPoint); string const finishCountry = m_countryFileFn(finalPoint); - return CalculateRoute(startCountry, finishCountry, false /* blockMwmBorders */, startPoint, - startDirection, finalPoint, adjust, delegate, route); -} - -IRouter::ResultCode IndexRouter::CalculateRoute(string const & startCountry, - string const & finishCountry, bool forSingleMwm, - m2::PointD const & startPoint, - m2::PointD const & startDirection, - m2::PointD const & finalPoint, bool adjust, - RouterDelegate const & delegate, Route & route) -{ try { auto const startFile = platform::CountryFile(startCountry); auto const finishFile = platform::CountryFile(finishCountry); - if (adjust && !m_lastRoute.IsEmpty() && finalPoint == m_lastRoute.GetFinish()) + if (adjustToPrevRoute && m_lastRoute && finalPoint == m_lastRoute->GetFinish()) { - double const distanceToRoute = m_lastRoute.CalcDistance(startPoint); + double const distanceToRoute = m_lastRoute->CalcDistance(startPoint); double const distanceToFinish = MercatorBounds::DistanceOnEarth(startPoint, finalPoint); - if (distanceToRoute <= kAdjustRange && distanceToFinish >= kMinDistanceToFinish) - return AdjustRoute(startFile, startPoint, startDirection, finalPoint, delegate, route); + if (distanceToRoute <= kAdjustRangeM && distanceToFinish >= kMinDistanceToFinishM) + { + auto code = AdjustRoute(startFile, startPoint, startDirection, finalPoint, delegate, route); + if (code != IRouter::RouteNotFound) + return code; + + LOG(LWARNING, ("Can't adjust route, do full rebuild, prev start:", + MercatorBounds::ToLatLon(m_lastRoute->GetStart()), ", start:", + MercatorBounds::ToLatLon(startPoint), ", finish:", + MercatorBounds::ToLatLon(finalPoint))); + } } - return DoCalculateRoute(startFile, finishFile, forSingleMwm, startPoint, startDirection, - finalPoint, delegate, route); + return DoCalculateRoute(startFile, finishFile, false /* forSingleMwm */, startPoint, + startDirection, finalPoint, delegate, route); } catch (RootException const & e) { LOG(LERROR, ("Can't find path from", MercatorBounds::ToLatLon(startPoint), "to", - MercatorBounds::ToLatLon(finalPoint), ":\n ", e.what())); + MercatorBounds::ToLatLon(finalPoint), ":\n ", e.what())); return IRouter::InternalError; } } @@ -193,7 +194,7 @@ IRouter::ResultCode IndexRouter::DoCalculateRoute(platform::CountryFile const & m2::PointD const & finalPoint, RouterDelegate const & delegate, Route & route) { - m_lastRoute.Clear(); + m_lastRoute.reset(); TrafficStash::Guard guard(*m_trafficStash); WorldGraph graph = MakeWorldGraph(); @@ -232,17 +233,20 @@ IRouter::ResultCode IndexRouter::DoCalculateRoute(platform::CountryFile const & AStarProgress progress(0, 100); progress.Initialize(starter.GetStartVertex().GetPoint(), starter.GetFinishVertex().GetPoint()); - uint32_t drawPointsStep = 0; + uint32_t visitCount = 0; + auto onVisitJunction = [&](Segment const & from, Segment const & to) { + if (++visitCount % kVisitPeriod != 0) + return; + m2::PointD const & pointFrom = starter.GetPoint(from, true /* front */); m2::PointD const & pointTo = starter.GetPoint(to, true /* front */); auto const lastValue = progress.GetLastValue(); auto const newValue = progress.GetProgressForBidirectedAlgo(pointFrom, pointTo); if (newValue - lastValue > kProgressInterval) delegate.OnProgress(newValue); - if (drawPointsStep % kDrawPointsPeriod == 0) - delegate.OnPointCheck(pointFrom); - ++drawPointsStep; + + delegate.OnPointCheck(pointFrom); }; RoutingResult routingResult; @@ -263,9 +267,12 @@ IRouter::ResultCode IndexRouter::DoCalculateRoute(platform::CountryFile const & if (redressResult != IRouter::NoError) return redressResult; - m_lastRoute.Init(startPoint, finalPoint); + m_lastRoute = make_unique(startPoint, finalPoint); for (Segment const & segment : routingResult.path) - m_lastRoute.AddStep(segment, starter.GetPoint(segment, true /* front */)); + { + if (!IndexGraphStarter::IsFakeSegment(segment)) + m_lastRoute->AddStep(segment, starter.GetPoint(segment, true /* front */)); + } return IRouter::NoError; } @@ -285,95 +292,55 @@ IRouter::ResultCode IndexRouter::AdjustRoute(platform::CountryFile const & start if (!FindClosestSegment(startCountry, startPoint, true /* isOutgoing */, graph, startSegment)) return IRouter::StartPointNotFound; - IndexGraphStarter starter( - IndexGraphStarter::FakeVertex(startSegment, startPoint), - IndexGraphStarter::FakeVertex(m_lastRoute.GetFinishSegment(), finalPoint), graph); + auto const & steps = m_lastRoute->GetSteps(); + + IndexGraphStarter starter(IndexGraphStarter::FakeVertex(startSegment, startPoint), + IndexGraphStarter::FakeVertex(steps.back().GetSegment(), finalPoint), + graph); AStarProgress progress(0, 100); progress.Initialize(starter.GetStartVertex().GetPoint(), starter.GetFinishVertex().GetPoint()); - uint32_t drawPointsStep = 0; - auto onVisitJunction = [&](Segment const & from, Segment const & /* to */) { - m2::PointD const & point = starter.GetPoint(from, true /* front */); + vector prevEdges; + for (auto const & step : steps) + prevEdges.emplace_back(step.GetSegment(), starter.CalcSegmentWeight(step.GetSegment())); + + uint32_t visitCount = 0; + + auto onVisitJunction = [&](Segment const & /* start */, Segment const & vertex) { + if (visitCount++ % kVisitPeriod != 0) + return; + + m2::PointD const & point = starter.GetPoint(vertex, true /* front */); auto const lastValue = progress.GetLastValue(); auto const newValue = progress.GetProgressForDirectedAlgo(point); if (newValue - lastValue > kProgressInterval) delegate.OnProgress(newValue); - if (drawPointsStep % kDrawPointsPeriod == 0) - delegate.OnPointCheck(point); - ++drawPointsStep; + + delegate.OnPointCheck(point); }; AStarAlgorithm algorithm; - RoutingResult routingResult; + RoutingResult result; + auto resultCode = ConvertResult(algorithm.AdjustRoute( + starter, starter.GetStart(), prevEdges, kAdjustLimitSec, result, delegate, onVisitJunction)); + if (resultCode != IRouter::NoError) + return resultCode; - auto const & steps = m_lastRoute.GetSteps(); - set routeSegmentsSet; - for (auto const & step : steps) - { - auto const & segment = step.GetSegment(); - if (!IndexGraphStarter::IsFakeSegment(segment)) - routeSegmentsSet.insert(segment); - } - - double const requiredDistanceToFinish = - MercatorBounds::DistanceOnEarth(startPoint, finalPoint) - kAdjustDistance; - CHECK_GREATER(requiredDistanceToFinish, 0.0, ()); - - auto const isFinalVertex = [&](Segment const & vertex) { - if (vertex == starter.GetFinish()) - return true; - - return routeSegmentsSet.count(vertex) > 0 && - MercatorBounds::DistanceOnEarth( - starter.GetPoint(vertex, true /* front */), finalPoint) <= requiredDistanceToFinish; - }; - - auto const code = ConvertResult( - algorithm.FindPath(starter, starter.GetStart(), starter.GetFinish(), routingResult, delegate, - onVisitJunction, isFinalVertex)); - if (code != IRouter::NoError) - return code; - - size_t const adjustingRouteSize = routingResult.path.size(); - AppendRemainingRoute(routingResult.path); - - auto const redressResult = RedressRoute(routingResult.path, delegate, false, starter, route); + result.path.push_back(starter.GetFinish()); + auto const redressResult = RedressRoute(result.path, delegate, false, starter, route); if (redressResult != IRouter::NoError) return redressResult; - LOG(LINFO, ("Adjust route, elapsed:", timer.ElapsedSeconds(), ", start:", - MercatorBounds::ToLatLon(startPoint), ", finish:", - MercatorBounds::ToLatLon(finalPoint), ", old route:", steps.size(), ", new route:", - routingResult.path.size(), ", adjust:", adjustingRouteSize)); + LOG(LINFO, + ("Adjust route, elapsed:", timer.ElapsedSeconds(), ", prev start:", + MercatorBounds::ToLatLon(m_lastRoute->GetStart()), ", start:", + MercatorBounds::ToLatLon(startPoint), ", finish:", MercatorBounds::ToLatLon(finalPoint), + ", prev route:", steps.size(), ", new route:", result.path.size())); return IRouter::NoError; } -void IndexRouter::AppendRemainingRoute(vector & route) const -{ - auto const steps = m_lastRoute.GetSteps(); - Segment const joinSegment = route.back(); - - // Route to finish found, append is not needed. - if (IndexGraphStarter::IsFakeSegment(joinSegment)) - return; - - for (size_t i = 0; i < steps.size(); ++i) - { - if (steps[i].GetSegment() == joinSegment) - { - for (size_t j = i + 1; j < steps.size(); ++j) - route.push_back(steps[j].GetSegment()); - - return; - } - } - - CHECK(false, - ("Can't find", joinSegment, ", m_routeSegments:", steps.size(), "path:", route.size())); -} - WorldGraph IndexRouter::MakeWorldGraph() { WorldGraph graph( diff --git a/routing/index_router.hpp b/routing/index_router.hpp index a2c003d064..8d4c1a2d8f 100644 --- a/routing/index_router.hpp +++ b/routing/index_router.hpp @@ -41,7 +41,7 @@ public: virtual string GetName() const override { return m_name; } virtual IRouter::ResultCode CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, bool adjust, + m2::PointD const & finalPoint, bool adjustToPrevRoute, RouterDelegate const & delegate, Route & route) override; @@ -54,11 +54,6 @@ public: Index & index); private: - IRouter::ResultCode CalculateRoute(string const & startCountry, string const & finishCountry, - bool forSingleMwm, m2::PointD const & startPoint, - m2::PointD const & startDirection, - m2::PointD const & finalPoint, bool adjust, - RouterDelegate const & delegate, Route & route); IRouter::ResultCode DoCalculateRoute(platform::CountryFile const & startCountry, platform::CountryFile const & finishCountry, bool forSingleMwm, m2::PointD const & startPoint, @@ -69,7 +64,6 @@ private: m2::PointD const & startPoint, m2::PointD const & startDirection, m2::PointD const & finalPoint, RouterDelegate const & delegate, Route & route); - void AppendRemainingRoute(std::vector & route) const; WorldGraph MakeWorldGraph(); @@ -103,6 +97,6 @@ private: shared_ptr m_vehicleModelFactory; shared_ptr m_estimator; unique_ptr m_directionsEngine; - SegmentedRoute m_lastRoute; + unique_ptr m_lastRoute; }; } // namespace routing diff --git a/routing/road_graph_router.hpp b/routing/road_graph_router.hpp index 280f96b23d..f790246305 100644 --- a/routing/road_graph_router.hpp +++ b/routing/road_graph_router.hpp @@ -35,7 +35,7 @@ public: string GetName() const override { return m_name; } void ClearState() override; ResultCode CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, bool adjust, + m2::PointD const & finalPoint, bool adjustToPrevRoute, RouterDelegate const & delegate, Route & route) override; private: diff --git a/routing/routing_algorithm.cpp b/routing/routing_algorithm.cpp index b93344f78a..2d3b1220ed 100644 --- a/routing/routing_algorithm.cpp +++ b/routing/routing_algorithm.cpp @@ -12,6 +12,7 @@ namespace routing namespace { +uint32_t constexpr kVisitPeriod = 4; float constexpr kProgressInterval = 2; double constexpr KMPH2MPS = 1000.0 / (60 * 60); @@ -137,10 +138,12 @@ IRoutingAlgorithm::Result AStarRoutingAlgorithm::CalculateRoute(IRoadGraph const RoutingResult & path) { AStarProgress progress(0, 100); + uint32_t visitCount = 0; + + auto onVisitJunctionFn = [&](Junction const & junction, Junction const & /* target */) { + if (++visitCount % kVisitPeriod != 0) + return; - function onVisitJunctionFn = - [&delegate, &progress](Junction const & junction, Junction const & /* target */) - { delegate.OnPointCheck(junction.GetPoint()); auto const lastValue = progress.GetLastValue(); auto const newValue = progress.GetProgressForDirectedAlgo(junction.GetPoint()); @@ -164,10 +167,12 @@ IRoutingAlgorithm::Result AStarBidirectionalRoutingAlgorithm::CalculateRoute( RouterDelegate const & delegate, RoutingResult & path) { AStarProgress progress(0, 100); + uint32_t visitCount = 0; + + auto onVisitJunctionFn = [&](Junction const & junction, Junction const & target) { + if (++visitCount % kVisitPeriod != 0) + return; - function onVisitJunctionFn = - [&delegate, &progress](Junction const & junction, Junction const & target) - { delegate.OnPointCheck(junction.GetPoint()); auto const lastValue = progress.GetLastValue(); auto const newValue = diff --git a/routing/routing_helpers.cpp b/routing/routing_helpers.cpp index 555ce45b8a..a6986faa57 100644 --- a/routing/routing_helpers.cpp +++ b/routing/routing_helpers.cpp @@ -73,21 +73,7 @@ void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, { traffic.reserve(segments.size()); for (Segment const & seg : segments) - { - traffic::TrafficInfo::RoadSegmentId roadSegment( - seg.GetFeatureId(), seg.GetSegmentIdx(), - seg.IsForward() ? traffic::TrafficInfo::RoadSegmentId::kForwardDirection - : traffic::TrafficInfo::RoadSegmentId::kReverseDirection); - - auto segTraffic = SpeedGroup::Unknown; - if (auto trafficColoring = trafficStash->Get(seg.GetMwmId())) - { - auto const it = trafficColoring->find(roadSegment); - if (it != trafficColoring->cend()) - segTraffic = it->second; - } - traffic.push_back(segTraffic); - } + traffic.push_back(trafficStash->GetSpeedGroup(seg)); CHECK_EQUAL(segments.size(), traffic.size(), ()); } diff --git a/routing/routing_integration_tests/routing_test_tools.cpp b/routing/routing_integration_tests/routing_test_tools.cpp index 6f504e715a..da74756a90 100644 --- a/routing/routing_integration_tests/routing_test_tools.cpp +++ b/routing/routing_integration_tests/routing_test_tools.cpp @@ -243,8 +243,8 @@ namespace integration IRouter * router = routerComponents.GetRouter(); ASSERT(router, ()); shared_ptr route(new Route("mapsme")); - IRouter::ResultCode result = - router->CalculateRoute(startPoint, startDirection, finalPoint, delegate, *route.get()); + IRouter::ResultCode result = router->CalculateRoute(startPoint, startDirection, finalPoint, + false /* adjust */, delegate, *route.get()); ASSERT(route, ()); return TRouteResult(route, result); } diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index b2d8b68db7..718ce0e212 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -84,7 +84,7 @@ void RoutingSession::BuildRoute(m2::PointD const & startPoint, m2::PointD const void RoutingSession::RebuildRoute(m2::PointD const & startPoint, TReadyCallback const & readyCallback, uint32_t timeoutSec, - State routeRebuildingState, bool adjust) + State routeRebuildingState, bool adjustToPrevRoute) { ASSERT(m_router != nullptr, ()); ASSERT_NOT_EQUAL(m_endPoint, m2::PointD::Zero(), ("End point was not set")); @@ -95,7 +95,7 @@ void RoutingSession::RebuildRoute(m2::PointD const & startPoint, // Use old-style callback construction, because lambda constructs buggy function on Android // (callback param isn't captured by value). - m_router->CalculateRoute(startPoint, startPoint - m_lastGoodPosition, m_endPoint, adjust, + m_router->CalculateRoute(startPoint, startPoint - m_lastGoodPosition, m_endPoint, adjustToPrevRoute, DoReadyCallback(*this, readyCallback, m_routingSessionMutex), m_progressCallback, timeoutSec); } @@ -157,7 +157,7 @@ void RoutingSession::RebuildRouteOnTrafficUpdate() // Cancel current route building if going. m_router->ClearState(); RebuildRoute(m_lastGoodPosition, m_rebuildReadyCallback, 0 /* timeoutSec */, - routing::RoutingSession::State::RouteRebuilding, false /* adjust */); + routing::RoutingSession::State::RouteRebuilding, false /* adjustToPrevRoute */); } void RoutingSession::Reset() diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 6acfe3e244..04abd78480 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -90,7 +90,7 @@ public: void BuildRoute(m2::PointD const & startPoint, m2::PointD const & endPoint, uint32_t timeoutSec); void RebuildRoute(m2::PointD const & startPoint, TReadyCallback const & readyCallback, - uint32_t timeoutSec, State routeRebuildingState, bool adjust); + uint32_t timeoutSec, State routeRebuildingState, bool adjustToPrevRoute); m2::PointD GetEndPoint() const { return m_endPoint; } bool IsActive() const { return (m_state != RoutingNotActive); } diff --git a/routing/routing_tests/astar_algorithm_test.cpp b/routing/routing_tests/astar_algorithm_test.cpp index f3887b3cc7..40c40b6015 100644 --- a/routing/routing_tests/astar_algorithm_test.cpp +++ b/routing/routing_tests/astar_algorithm_test.cpp @@ -57,10 +57,10 @@ private: map> m_adjs; }; +using TAlgorithm = AStarAlgorithm; + void TestAStar(UndirectedGraph & graph, vector const & expectedRoute, double const & expectedDistance) { - using TAlgorithm = AStarAlgorithm; - TAlgorithm algo; RoutingResult actualRoute; @@ -90,4 +90,68 @@ UNIT_TEST(AStarAlgorithm_Sample) TestAStar(graph, expectedRoute, 23); } +UNIT_TEST(AdjustRoute) +{ + UndirectedGraph graph; + + for (unsigned int i = 0; i < 5; ++i) + graph.AddEdge(i /* from */, i + 1 /* to */, 1 /* weight */); + + graph.AddEdge(6, 0, 1); + graph.AddEdge(6, 1, 1); + graph.AddEdge(6, 2, 1); + + // Each edge contains {vertexId, weight}. + vector const prevRoute = {{0, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}; + + TAlgorithm algo; + RoutingResult result; + auto code = algo.AdjustRoute(graph, 6 /* start */, prevRoute, 1.0 /* limit */, result, + my::Cancellable(), nullptr /* onVisitedVertexCallback */); + + vector const expectedRoute = {6, 2, 3, 4, 5}; + TEST_EQUAL(code, TAlgorithm::Result::OK, ()); + TEST_EQUAL(result.path, expectedRoute, ()); + TEST_EQUAL(result.distance, 4.0, ()); +} + +UNIT_TEST(AdjustRouteNoPath) +{ + UndirectedGraph graph; + + for (unsigned int i = 0; i < 5; ++i) + graph.AddEdge(i /* from */, i + 1 /* to */, 1 /* weight */); + + // Each edge contains {vertexId, weight}. + vector const prevRoute = {{0, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}; + + TAlgorithm algo; + RoutingResult result; + auto code = algo.AdjustRoute(graph, 6 /* start */, prevRoute, 1.0 /* limit */, result, + my::Cancellable(), nullptr /* onVisitedVertexCallback */); + + TEST_EQUAL(code, TAlgorithm::Result::NoPath, ()); + TEST(result.path.empty(), ()); +} + +UNIT_TEST(AdjustRouteOutOfLimit) +{ + UndirectedGraph graph; + + for (unsigned int i = 0; i < 5; ++i) + graph.AddEdge(i /* from */, i + 1 /* to */, 1 /* weight */); + + graph.AddEdge(6, 2, 2); + + // Each edge contains {vertexId, weight}. + vector const prevRoute = {{0, 0}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}}; + + TAlgorithm algo; + RoutingResult result; + auto code = algo.AdjustRoute(graph, 6 /* start */, prevRoute, 1.0 /* limit */, result, + my::Cancellable(), nullptr /* onVisitedVertexCallback */); + + TEST_EQUAL(code, TAlgorithm::Result::NoPath, ()); + TEST(result.path.empty(), ()); +} } // namespace routing_test diff --git a/routing/routing_tests/async_router_test.cpp b/routing/routing_tests/async_router_test.cpp index 6aeb0ba1dc..5063463751 100644 --- a/routing/routing_tests/async_router_test.cpp +++ b/routing/routing_tests/async_router_test.cpp @@ -30,7 +30,7 @@ public: // IRouter overrides: string GetName() const override { return "Dummy"; } ResultCode CalculateRoute(m2::PointD const & startPoint, m2::PointD const & startDirection, - m2::PointD const & finalPoint, bool adjust, + m2::PointD const & finalPoint, bool adjustToPrevRoute, RouterDelegate const & delegate, Route & route) override { vector points({startPoint, finalPoint}); @@ -97,7 +97,7 @@ UNIT_TEST(NeedMoreMapsSignalTest) DummyResultCallback resultCallback(2 /* expectedCalls */); AsyncRouter async(DummyStatisticsCallback, nullptr /* pointCheckCallback */); async.SetRouter(move(router), move(fetcher)); - async.CalculateRoute({1, 2}, {3, 4}, {5, 6}, false /* rebuild */, + async.CalculateRoute({1, 2}, {3, 4}, {5, 6}, false /* adjustToPrevRoute */, bind(ref(resultCallback), _1, _2), nullptr /* progressCallback */, 0 /* timeoutSec */); @@ -119,7 +119,7 @@ UNIT_TEST(StandartAsyncFogTest) DummyResultCallback resultCallback(1 /* expectedCalls */); AsyncRouter async(DummyStatisticsCallback, nullptr /* pointCheckCallback */); async.SetRouter(move(router), move(fetcher)); - async.CalculateRoute({1, 2}, {3, 4}, {5, 6}, false /* rebuild */, + async.CalculateRoute({1, 2}, {3, 4}, {5, 6}, false /* adjustToPrevRoute */, bind(ref(resultCallback), _1, _2), nullptr /* progressCallback */, 0 /* timeoutSec */); diff --git a/routing/segmented_route.cpp b/routing/segmented_route.cpp index dbd475d379..9fdf6aa3ae 100644 --- a/routing/segmented_route.cpp +++ b/routing/segmented_route.cpp @@ -1,5 +1,7 @@ #include "routing/segmented_route.hpp" +#include "routing/index_graph_starter.hpp" + #include "geometry/mercator.hpp" #include "base/assert.hpp" @@ -9,11 +11,9 @@ namespace routing { -void SegmentedRoute::Init(m2::PointD const & start, m2::PointD const & finish) +SegmentedRoute::SegmentedRoute(m2::PointD const & start, m2::PointD const & finish) + : m_start(start), m_finish(finish) { - m_start = start; - m_finish = finish; - m_steps.clear(); } double SegmentedRoute::CalcDistance(m2::PointD const & point) const @@ -26,11 +26,4 @@ double SegmentedRoute::CalcDistance(m2::PointD const & point) const return result; } - -Segment const & SegmentedRoute::GetFinishSegment() const -{ - // Last segment is fake, before last is finish - CHECK_GREATER(m_steps.size(), 2, ()); - return m_steps[m_steps.size() - 2].GetSegment(); -} } // namespace routing diff --git a/routing/segmented_route.hpp b/routing/segmented_route.hpp index c393d88cec..296e8eb1c0 100644 --- a/routing/segmented_route.hpp +++ b/routing/segmented_route.hpp @@ -8,48 +8,41 @@ namespace routing { -class SegmentedRouteStep final -{ -public: - SegmentedRouteStep() = default; - - SegmentedRouteStep(Segment const & segment, m2::PointD const & point) - : m_segment(segment), m_point(point) - { - } - - Segment const & GetSegment() const { return m_segment; } - m2::PointD const & GetPoint() const { return m_point; } - -private: - Segment m_segment; - // The front point of segment - m2::PointD m_point = m2::PointD::Zero(); -}; - class SegmentedRoute final { public: - void Init(m2::PointD const & start, m2::PointD const & finish); + class Step final + { + public: + Step() = default; + Step(Segment const & segment, m2::PointD const & point) : m_segment(segment), m_point(point) {} + + Segment const & GetSegment() const { return m_segment; } + m2::PointD const & GetPoint() const { return m_point; } + + private: + Segment const m_segment; + // The front point of segment + m2::PointD const m_point = m2::PointD::Zero(); + }; + + SegmentedRoute(m2::PointD const & start, m2::PointD const & finish); void AddStep(Segment const & segment, m2::PointD const & point) { m_steps.emplace_back(segment, point); } - void Clear() { Init(m2::PointD::Zero(), m2::PointD::Zero()); } - double CalcDistance(m2::PointD const & point) const; - Segment const & GetFinishSegment() const; m2::PointD const & GetStart() const { return m_start; } m2::PointD const & GetFinish() const { return m_finish; } - std::vector const & GetSteps() const { return m_steps; } + std::vector const & GetSteps() const { return m_steps; } bool IsEmpty() const { return m_steps.empty(); } private: - m2::PointD m_start = m2::PointD::Zero(); - m2::PointD m_finish = m2::PointD::Zero(); - std::vector m_steps; + m2::PointD const m_start; + m2::PointD const m_finish; + std::vector m_steps; }; } // namespace routing diff --git a/routing/traffic_stash.cpp b/routing/traffic_stash.cpp index 04c2856b5b..3aaa9158cd 100644 --- a/routing/traffic_stash.cpp +++ b/routing/traffic_stash.cpp @@ -6,6 +6,12 @@ namespace routing { +TrafficStash::TrafficStash(traffic::TrafficCache const & source, shared_ptr numMwmIds) + : m_source(source), m_numMwmIds(std::move(numMwmIds)) +{ + CHECK(m_numMwmIds, ()); +} + traffic::SpeedGroup TrafficStash::GetSpeedGroup(Segment const & segment) const { auto itMwm = m_mwmToTraffic.find(segment.GetMwmId()); @@ -24,6 +30,17 @@ traffic::SpeedGroup TrafficStash::GetSpeedGroup(Segment const & segment) const return itSeg->second; } +void TrafficStash::SetColoring(NumMwmId numMwmId, + std::shared_ptr coloring) +{ + m_mwmToTraffic[numMwmId] = coloring; +} + +bool TrafficStash::Has(NumMwmId numMwmId) const +{ + return m_mwmToTraffic.find(numMwmId) != m_mwmToTraffic.cend(); +} + void TrafficStash::CopyTraffic() { std::map> copy; diff --git a/routing/traffic_stash.hpp b/routing/traffic_stash.hpp index 679ebb686e..451e85e0cd 100644 --- a/routing/traffic_stash.hpp +++ b/routing/traffic_stash.hpp @@ -10,6 +10,7 @@ #include "base/assert.hpp" +#include #include namespace routing @@ -27,23 +28,11 @@ public: TrafficStash & m_stash; }; - TrafficStash(traffic::TrafficCache const & source, shared_ptr numMwmIds) - : m_source(source), m_numMwmIds(numMwmIds) - { - CHECK(m_numMwmIds, ()); - } + TrafficStash(traffic::TrafficCache const & source, std::shared_ptr numMwmIds); traffic::SpeedGroup GetSpeedGroup(Segment const & segment) const; - - void SetColoring(NumMwmId numMwmId, std::shared_ptr coloring) - { - m_mwmToTraffic[numMwmId] = coloring; - } - - bool Has(NumMwmId numMwmId) const - { - return m_mwmToTraffic.find(numMwmId) != m_mwmToTraffic.cend(); - } + void SetColoring(NumMwmId numMwmId, std::shared_ptr coloring); + bool Has(NumMwmId numMwmId) const; private: void CopyTraffic(); @@ -52,6 +41,6 @@ private: traffic::TrafficCache const & m_source; shared_ptr m_numMwmIds; - std::unordered_map> m_mwmToTraffic; + std::unordered_map> m_mwmToTraffic; }; } // namespace routing diff --git a/xcode/routing/routing.xcodeproj/project.pbxproj b/xcode/routing/routing.xcodeproj/project.pbxproj index aaedc75fb7..fd2dd59385 100644 --- a/xcode/routing/routing.xcodeproj/project.pbxproj +++ b/xcode/routing/routing.xcodeproj/project.pbxproj @@ -13,7 +13,6 @@ 0C08AA391DF8329B004195DD /* routing_exceptions.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C08AA381DF8329B004195DD /* routing_exceptions.hpp */; }; 0C090C811E4E274000D52AFD /* index_graph_loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C090C7F1E4E274000D52AFD /* index_graph_loader.cpp */; }; 0C090C821E4E274000D52AFD /* index_graph_loader.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C090C801E4E274000D52AFD /* index_graph_loader.hpp */; }; - 0C090C841E4E275E00D52AFD /* traffic_stash.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C090C831E4E275E00D52AFD /* traffic_stash.hpp */; }; 0C090C871E4E276700D52AFD /* world_graph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C090C851E4E276700D52AFD /* world_graph.cpp */; }; 0C090C881E4E276700D52AFD /* world_graph.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C090C861E4E276700D52AFD /* world_graph.hpp */; }; 0C0DF9211DE898B70055A22F /* index_graph_starter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C0DF91F1DE898B70055A22F /* index_graph_starter.cpp */; }; @@ -45,10 +44,11 @@ 0C5FEC6B1DDE193F0017688C /* road_point.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C5FEC681DDE193F0017688C /* road_point.hpp */; }; 0C5FEC6D1DDE19A40017688C /* index_graph_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C5FEC6C1DDE19A40017688C /* index_graph_test.cpp */; }; 0C62BFE61E8ADC3100055A79 /* coding.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C62BFE51E8ADC3100055A79 /* coding.hpp */; }; + 0C81E1531F02589800DC66DF /* traffic_stash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C81E1511F02589800DC66DF /* traffic_stash.cpp */; }; + 0C81E1541F02589800DC66DF /* traffic_stash.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C81E1521F02589800DC66DF /* traffic_stash.hpp */; }; + 0C81E1571F0258AA00DC66DF /* segmented_route.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C81E1551F0258AA00DC66DF /* segmented_route.cpp */; }; + 0C81E1581F0258AA00DC66DF /* segmented_route.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C81E1561F0258AA00DC66DF /* segmented_route.hpp */; }; 0C8705051E0182F200BCAF71 /* route_point.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0C8705041E0182F200BCAF71 /* route_point.hpp */; }; - 0CA683581EE04ADB004B7269 /* segmented_route.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CA683561EE04ADB004B7269 /* segmented_route.cpp */; }; - 0CA683591EE04ADB004B7269 /* segmented_route.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0CA683571EE04ADB004B7269 /* segmented_route.hpp */; }; - 0CA6835B1EE04AF3004B7269 /* traffic_stash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CA6835A1EE04AF3004B7269 /* traffic_stash.cpp */; }; 0CF5E8AA1E8EA7A1001ED497 /* coding_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CF5E8A91E8EA7A1001ED497 /* coding_test.cpp */; }; 3462FDAD1DC1E5BF00906FD7 /* libopening_hours.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3462FDAC1DC1E5BF00906FD7 /* libopening_hours.a */; }; 349D1CE01E3F589900A878FD /* restrictions_serialization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 349D1CDE1E3F589900A878FD /* restrictions_serialization.cpp */; }; @@ -272,7 +272,6 @@ 0C08AA381DF8329B004195DD /* routing_exceptions.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = routing_exceptions.hpp; sourceTree = ""; }; 0C090C7F1E4E274000D52AFD /* index_graph_loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_graph_loader.cpp; sourceTree = ""; }; 0C090C801E4E274000D52AFD /* index_graph_loader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = index_graph_loader.hpp; sourceTree = ""; }; - 0C090C831E4E275E00D52AFD /* traffic_stash.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = traffic_stash.hpp; sourceTree = ""; }; 0C090C851E4E276700D52AFD /* world_graph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = world_graph.cpp; sourceTree = ""; }; 0C090C861E4E276700D52AFD /* world_graph.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = world_graph.hpp; sourceTree = ""; }; 0C0DF91F1DE898B70055A22F /* index_graph_starter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_graph_starter.cpp; sourceTree = ""; }; @@ -304,10 +303,11 @@ 0C5FEC681DDE193F0017688C /* road_point.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = road_point.hpp; sourceTree = ""; }; 0C5FEC6C1DDE19A40017688C /* index_graph_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_graph_test.cpp; sourceTree = ""; }; 0C62BFE51E8ADC3100055A79 /* coding.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = coding.hpp; sourceTree = ""; }; + 0C81E1511F02589800DC66DF /* traffic_stash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = traffic_stash.cpp; sourceTree = ""; }; + 0C81E1521F02589800DC66DF /* traffic_stash.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = traffic_stash.hpp; sourceTree = ""; }; + 0C81E1551F0258AA00DC66DF /* segmented_route.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = segmented_route.cpp; sourceTree = ""; }; + 0C81E1561F0258AA00DC66DF /* segmented_route.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = segmented_route.hpp; sourceTree = ""; }; 0C8705041E0182F200BCAF71 /* route_point.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = route_point.hpp; sourceTree = ""; }; - 0CA683561EE04ADB004B7269 /* segmented_route.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = segmented_route.cpp; sourceTree = ""; }; - 0CA683571EE04ADB004B7269 /* segmented_route.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = segmented_route.hpp; sourceTree = ""; }; - 0CA6835A1EE04AF3004B7269 /* traffic_stash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = traffic_stash.cpp; sourceTree = ""; }; 0CF5E8A91E8EA7A1001ED497 /* coding_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coding_test.cpp; sourceTree = ""; }; 3462FDAC1DC1E5BF00906FD7 /* libopening_hours.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libopening_hours.a; path = "../../../omim-build/xcode/Debug/libopening_hours.a"; sourceTree = ""; }; 349D1CDE1E3F589900A878FD /* restrictions_serialization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = restrictions_serialization.cpp; sourceTree = ""; }; @@ -819,12 +819,12 @@ 670EE55B1B6001E7001E8064 /* routing_session.hpp */, 670EE55C1B6001E7001E8064 /* routing_settings.hpp */, 0C470E6F1E0D4EB1005B824D /* segment.hpp */, - 0CA683561EE04ADB004B7269 /* segmented_route.cpp */, - 0CA683571EE04ADB004B7269 /* segmented_route.hpp */, + 0C81E1551F0258AA00DC66DF /* segmented_route.cpp */, + 0C81E1561F0258AA00DC66DF /* segmented_route.hpp */, A1876BC41BB19C4300C9C743 /* speed_camera.cpp */, A1876BC51BB19C4300C9C743 /* speed_camera.hpp */, - 0CA6835A1EE04AF3004B7269 /* traffic_stash.cpp */, - 0C090C831E4E275E00D52AFD /* traffic_stash.hpp */, + 0C81E1511F02589800DC66DF /* traffic_stash.cpp */, + 0C81E1521F02589800DC66DF /* traffic_stash.hpp */, 56099E271CC7C97D00A7772A /* turn_candidate.hpp */, 674F9BC61B0A580E00704FFA /* turns_generator.cpp */, 674F9BC71B0A580E00704FFA /* turns_generator.hpp */, @@ -874,7 +874,6 @@ 0C5BC9D21E28FD4E0071BFDD /* index_road_graph.hpp in Headers */, 674F9BD11B0A580E00704FFA /* online_cross_fetcher.hpp in Headers */, 0C470E701E0D4EB1005B824D /* segment.hpp in Headers */, - 0C090C841E4E275E00D52AFD /* traffic_stash.hpp in Headers */, A120B3531B4A7C1C002F3808 /* astar_algorithm.hpp in Headers */, 0C5FEC5F1DDE192A0017688C /* geometry.hpp in Headers */, 674A28B21B1605D2001A525C /* osrm_engine.hpp in Headers */, @@ -902,6 +901,7 @@ 56099E291CC7C97D00A7772A /* loaded_path_segment.hpp in Headers */, 670EE55F1B6001E7001E8064 /* routing_settings.hpp in Headers */, 56CA09E61E30E73B00D05C9A /* index_graph_tools.hpp in Headers */, + 0C81E1581F0258AA00DC66DF /* segmented_route.hpp in Headers */, 671F58BE1B874EC80032311E /* followed_polyline.hpp in Headers */, 0C5FEC6A1DDE193F0017688C /* road_index.hpp in Headers */, 674F9BCD1B0A580E00704FFA /* features_road_graph.hpp in Headers */, @@ -913,6 +913,7 @@ 0C090C821E4E274000D52AFD /* index_graph_loader.hpp in Headers */, 670EE5721B664796001E8064 /* directions_engine.hpp in Headers */, 56C439291E93BF8C00998E29 /* cross_mwm_graph.hpp in Headers */, + 0C81E1541F02589800DC66DF /* traffic_stash.hpp in Headers */, 0C8705051E0182F200BCAF71 /* route_point.hpp in Headers */, A1876BC71BB19C4300C9C743 /* speed_camera.hpp in Headers */, 56EA2FD51D8FD8590083F01A /* routing_helpers.hpp in Headers */, @@ -929,7 +930,6 @@ 0C5FEC6B1DDE193F0017688C /* road_point.hpp in Headers */, 56099E2B1CC7C97D00A7772A /* turn_candidate.hpp in Headers */, 56C4392D1E93E5DF00998E29 /* transition_points.hpp in Headers */, - 0CA683591EE04ADB004B7269 /* segmented_route.hpp in Headers */, 0C5FEC551DDE191E0017688C /* edge_estimator.hpp in Headers */, 670B84C11A9381D900CE4492 /* cross_routing_context.hpp in Headers */, 0C12ED241E5C822A0080D0F4 /* index_router.hpp in Headers */, @@ -1168,6 +1168,7 @@ 6753441B1A3F644F00A0A8C3 /* route.cpp in Sources */, 674F9BCA1B0A580E00704FFA /* async_router.cpp in Sources */, 0C5F5D221E798B0400307B98 /* cross_mwm_connector.cpp in Sources */, + 0C81E1531F02589800DC66DF /* traffic_stash.cpp in Sources */, 0CF5E8AA1E8EA7A1001ED497 /* coding_test.cpp in Sources */, 675344191A3F644F00A0A8C3 /* osrm2feature_map.cpp in Sources */, 670D049E1B0B4A970013A7AC /* nearest_edge_finder.cpp in Sources */, @@ -1185,6 +1186,7 @@ 0C08AA341DF83223004195DD /* index_graph_serialization.cpp in Sources */, 5694CECA1EBA25F7004576D3 /* road_access_serialization.cpp in Sources */, 674F9BD41B0A580E00704FFA /* road_graph.cpp in Sources */, + 0C81E1571F0258AA00DC66DF /* segmented_route.cpp in Sources */, 56CA09E51E30E73B00D05C9A /* index_graph_tools.cpp in Sources */, 0C0DF92A1DE898FF0055A22F /* routing_helpers.cpp in Sources */, 67AB92E61B7B3E6E00AB5194 /* turns_tts_text.cpp in Sources */,