diff --git a/routing/bicycle_directions.cpp b/routing/bicycle_directions.cpp index c93a54000c..eb5593d39a 100644 --- a/routing/bicycle_directions.cpp +++ b/routing/bicycle_directions.cpp @@ -182,12 +182,6 @@ void BicycleDirectionsEngine::Generate(RoadGraphBase const & graph, vector const & path, - Route::TTimes & times) const -{ - times.clear(); - if (path.size() < 1) - return; - - // graph.GetMaxSpeedKMPH() below is used on purpose. - // The idea is while pedestrian (bicycle) routing ways for pedestrians (cyclists) are preferred. - // At the same time routing along big roads is still possible but if there's - // a pedestrian (bicycle) alternative it's prefered. To implement it a small speed - // is set in pedestrian_model (bicycle_model) for big roads. On the other hand - // the most likely a pedestrian (a cyclist) will go along big roads with average - // speed (graph.GetMaxSpeedKMPH()). - double const speedMPS = graph.GetMaxSpeedKMPH() * KMPH2MPS; - - times.reserve(path.size()); - - double trackTimeSec = 0.0; - times.emplace_back(0, trackTimeSec); - - m2::PointD prev = path[0].GetPoint(); - for (size_t i = 1; i < path.size(); ++i) - { - m2::PointD const & curr = path[i].GetPoint(); - - double const lengthM = MercatorBounds::DistanceOnEarth(prev, curr); - trackTimeSec += lengthM / speedMPS; - - times.emplace_back(i, trackTimeSec); - - prev = curr; - } -} - bool IDirectionsEngine::ReconstructPath(RoadGraphBase const & graph, vector const & path, vector & routeEdges, my::Cancellable const & cancellable) const diff --git a/routing/directions_engine.hpp b/routing/directions_engine.hpp index 51ed5731c3..a897d4640c 100644 --- a/routing/directions_engine.hpp +++ b/routing/directions_engine.hpp @@ -29,8 +29,5 @@ protected: /// was cancelled and in case of extremely short paths of 0 or 1 point. Returns true otherwise. bool ReconstructPath(RoadGraphBase const & graph, std::vector const & path, std::vector & routeEdges, my::Cancellable const & cancellable) const; - - void CalculateTimes(RoadGraphBase const & graph, std::vector const & path, - Route::TTimes & times) const; }; } // namespace routing diff --git a/routing/index_road_graph.cpp b/routing/index_road_graph.cpp index 328a1c4f82..26ab50c5b8 100644 --- a/routing/index_road_graph.cpp +++ b/routing/index_road_graph.cpp @@ -32,8 +32,8 @@ void IndexRoadGraph::GetIngoingEdges(Junction const & junction, TEdgeVector & ed double IndexRoadGraph::GetMaxSpeedKMPH() const { // Value doesn't matter. - // It used in IDirectionsEngine::CalculateTimes only. - // But SingleMwmRouter::RedressRoute overwrites time values. + // It is used in CalculateMaxSpeedTimes only. + // Then SingleMwmRouter::RedressRoute overwrites time values. // // TODO: remove this stub after transfering Bicycle and Pedestrian to index routing. return 0.0; diff --git a/routing/index_router.cpp b/routing/index_router.cpp index 88d55ca211..d7432e8527 100644 --- a/routing/index_router.cpp +++ b/routing/index_router.cpp @@ -472,17 +472,7 @@ IRouter::ResultCode IndexRouter::RedressRoute(vector const & segments, IndexRoadGraph roadGraph(m_numMwmIds, starter, segments, junctions, m_index); if (!forSingleMwm) starter.GetGraph().SetMode(WorldGraph::Mode::NoLeaps); - - CHECK(m_directionsEngine, ()); - ReconstructRoute(*m_directionsEngine, roadGraph, m_trafficStash, delegate, - false /* hasAltitude */, junctions, route); - - if (!route.IsValid()) - { - LOG(LERROR, ("ReconstructRoute failed. Segments:", segments.size())); - return IRouter::InternalError; - } - + Route::TTimes times; times.reserve(segments.size()); double time = 0.0; @@ -493,8 +483,16 @@ IRouter::ResultCode IndexRouter::RedressRoute(vector const & segments, times.emplace_back(static_cast(i), time); time += starter.CalcSegmentWeight(segments[i]); } + + CHECK(m_directionsEngine, ()); + ReconstructRoute(*m_directionsEngine, roadGraph, m_trafficStash, delegate, false /* hasAltitude */, junctions, + std::move(times), route); - route.SetSectionTimes(move(times)); + if (!route.IsValid()) + { + LOG(LERROR, ("ReconstructRoute failed. Segments:", segments.size())); + return IRouter::InternalError; + } if (delegate.IsCancelled()) return IRouter::Cancelled; diff --git a/routing/pedestrian_directions.cpp b/routing/pedestrian_directions.cpp index 4030dc182c..7625468b9b 100644 --- a/routing/pedestrian_directions.cpp +++ b/routing/pedestrian_directions.cpp @@ -42,12 +42,11 @@ PedestrianDirectionsEngine::PedestrianDirectionsEngine(shared_ptr num void PedestrianDirectionsEngine::Generate(RoadGraphBase const & graph, vector const & path, my::Cancellable const & cancellable, - Route::TTimes & times, Route::TTurns & turns, + Route::TTimes & /* times */, Route::TTurns & turns, Route::TStreets & streetNames, vector & routeGeometry, vector & segments) { - times.clear(); turns.clear(); streetNames.clear(); routeGeometry.clear(); @@ -56,8 +55,6 @@ void PedestrianDirectionsEngine::Generate(RoadGraphBase const & graph, if (path.size() <= 1) return; - CalculateTimes(graph, path, times); - vector routeEdges; if (!ReconstructPath(graph, path, routeEdges, cancellable)) { diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index fe1ba87524..0c782a2fe0 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -203,9 +203,12 @@ IRouter::ResultCode RoadGraphRouter::CalculateRoute(m2::PointD const & startPoin ASSERT_EQUAL(result.path.back(), finalPos, ()); ASSERT_GREATER(result.distance, 0., ()); + Route::TTimes times; + CalculateMaxSpeedTimes(*m_roadGraph, result.path, times); + CHECK(m_directionsEngine, ()); - ReconstructRoute(*m_directionsEngine, *m_roadGraph, nullptr, delegate, true /* hasAltitude */, - result.path, route); + ReconstructRoute(*m_directionsEngine, *m_roadGraph, nullptr, delegate, true, result.path, + std::move(times), route); } m_roadGraph->ResetFakes(); diff --git a/routing/routing_helpers.cpp b/routing/routing_helpers.cpp index a6986faa57..56b15f8800 100644 --- a/routing/routing_helpers.cpp +++ b/routing/routing_helpers.cpp @@ -6,15 +6,22 @@ #include "base/stl_helpers.hpp" #include +#include + +namespace +{ +double constexpr KMPH2MPS = 1000.0 / (60 * 60); +} // namespace namespace routing { +using namespace std; using namespace traffic; void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, shared_ptr const & trafficStash, my::Cancellable const & cancellable, bool hasAltitude, - vector & path, Route & route) + vector const & path, Route::TTimes && times, Route & route) { if (path.empty()) { @@ -22,18 +29,15 @@ void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, return; } - // By some reason there're two adjacent positions on a road with - // the same end-points. This could happen, for example, when - // direction on a road was changed. But it doesn't matter since - // this code reconstructs only geometry of a route. - path.erase(unique(path.begin(), path.end()), path.end()); + CHECK_EQUAL(path.size(), times.size(), ()); - Route::TTimes times; + Route::TTimes dummyTimes; Route::TTurns turnsDir; vector junctions; Route::TStreets streetNames; vector segments; - engine.Generate(graph, path, cancellable, times, turnsDir, streetNames, junctions, segments); + // @TODO It's necessary to remove |dummyTimes| from Generate() and MakeTurnAnnotation() methods.. + engine.Generate(graph, path, cancellable, dummyTimes, turnsDir, streetNames, junctions, segments); CHECK_EQUAL(segments.size() + 1, junctions.size(), ()); if (cancellable.IsCancelled()) @@ -90,4 +94,39 @@ Segment ConvertEdgeToSegment(NumMwmIds const & numMwmIds, Edge const & edge) numMwmIds.GetId(edge.GetFeatureId().m_mwmId.GetInfo()->GetLocalFile().GetCountryFile()); return Segment(numMwmId, edge.GetFeatureId().m_index, edge.GetSegId(), edge.IsForward()); } -} // namespace rouing + +void CalculateMaxSpeedTimes(RoadGraphBase const & graph, vector const & path, + Route::TTimes & times) +{ + times.clear(); + if (path.size() < 1) + return; + + // graph.GetMaxSpeedKMPH() below is used on purpose. + // The idea is while pedestrian (bicycle) routing ways for pedestrians (cyclists) are preferred. + // At the same time routing along big roads is still possible but if there's + // a pedestrian (bicycle) alternative it's prefered. To implement it a small speed + // is set in pedestrian_model (bicycle_model) for big roads. On the other hand + // the most likely a pedestrian (a cyclist) will go along big roads with average + // speed (graph.GetMaxSpeedKMPH()). + double const speedMPS = graph.GetMaxSpeedKMPH() * KMPH2MPS; + + times.reserve(path.size()); + + double trackTimeSec = 0.0; + times.emplace_back(0, trackTimeSec); + + m2::PointD prev = path[0].GetPoint(); + for (size_t i = 1; i < path.size(); ++i) + { + m2::PointD const & curr = path[i].GetPoint(); + + double const lengthM = MercatorBounds::DistanceOnEarth(prev, curr); + trackTimeSec += lengthM / speedMPS; + + times.emplace_back(i, trackTimeSec); + + prev = curr; + } +} +} // namespace routing diff --git a/routing/routing_helpers.hpp b/routing/routing_helpers.hpp index 85e8ad5635..42b7364ec4 100644 --- a/routing/routing_helpers.hpp +++ b/routing/routing_helpers.hpp @@ -32,12 +32,16 @@ bool IsRoad(TTypes const & types) void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, shared_ptr const & trafficStash, my::Cancellable const & cancellable, bool hasAltitude, - vector & path, Route & route); + vector const & path, Route::TTimes && times, Route & route); /// \brief Converts |edge| to |segment|. /// \returns false if mwm of |edge| is not alive. Segment ConvertEdgeToSegment(NumMwmIds const & numMwmIds, Edge const & edge); +/// \brief Fills |times| according to max speed at |graph| and |path|. +void CalculateMaxSpeedTimes(RoadGraphBase const & graph, vector const & path, + Route::TTimes & times); + /// \brief Checks is edge connected with world graph. Function does BFS while it finds some number /// of edges, /// if graph ends before this number is reached then junction is assumed as not connected to the