diff --git a/routing/directions_engine.hpp b/routing/directions_engine.hpp index 934be0f188..3dc487e405 100644 --- a/routing/directions_engine.hpp +++ b/routing/directions_engine.hpp @@ -18,6 +18,9 @@ class IDirectionsEngine public: virtual ~IDirectionsEngine() = default; + // @TODO(bykoianko) After fields |m_turns|, |m_times|, |m_streets| and |m_traffic| + // will be removed from class Route the method Generate() should fill + // vector instead of |turns|, |streetNames|, |routeGeometry| and |segments|. virtual void Generate(RoadGraphBase const & graph, vector const & path, my::Cancellable const & cancellable, Route::TTurns & turns, Route::TStreets & streetNames, vector & routeGeometry, diff --git a/routing/route.cpp b/routing/route.cpp index 7eef3fa618..a896089031 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -75,33 +75,6 @@ double Route::GetCurrentDistanceFromBeginMeters() const return m_poly.GetDistanceFromBeginM(); } -void Route::GetTurnsDistances(vector & distances) const -{ - distances.clear(); - if (!m_poly.IsValid()) - return; - - double mercatorDistance = 0.0; - auto const & polyline = m_poly.GetPolyline(); - for (auto currentTurn = m_turns.begin(); currentTurn != m_turns.end(); ++currentTurn) - { - // Skip turns at side points of the polyline geometry. We can't display them properly. - if (currentTurn->m_index == 0 || currentTurn->m_index == (polyline.GetSize() - 1)) - continue; - - uint32_t formerTurnIndex = 0; - if (currentTurn != m_turns.begin()) - formerTurnIndex = (currentTurn - 1)->m_index; - - //TODO (ldragunov) Extract CalculateMercatorDistance higher to avoid including turns generator. - double const mercatorDistanceBetweenTurns = - CalculateMercatorDistanceAlongPath(formerTurnIndex, currentTurn->m_index, polyline.GetPoints()); - mercatorDistance += mercatorDistanceBetweenTurns; - - distances.push_back(mercatorDistance); - } -} - double Route::GetCurrentDistanceToEndMeters() const { if (!m_poly.IsValid()) diff --git a/routing/route.hpp b/routing/route.hpp index 5409ff4e4c..33c05639a6 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -19,6 +19,7 @@ #include #include +#include #include namespace location @@ -135,6 +136,7 @@ public: inline void SetStreetNames(TStreets && v) { m_streets = move(v); } inline void SetAltitudes(feature::TAltitudes && v) { m_altitudes = move(v); } inline void SetTraffic(vector && v) { m_traffic = move(v); } + inline void SetSegmentInfo(vector && v) {m_segmentInfo = std::move(v);} uint32_t GetTotalTimeSec() const; uint32_t GetCurrentTimeToEndSec() const; @@ -147,8 +149,6 @@ public: feature::TAltitudes const & GetAltitudes() const { return m_altitudes; } vector const & GetTraffic() const { return m_traffic; } vector const & GetSegDistanceMeters() const { return m_poly.GetSegDistanceM(); } - /// \returns distance to all turns in mercator. - void GetTurnsDistances(vector & distances) const; bool IsValid() const { return (m_poly.GetPolyline().GetSize() > 1); } double GetTotalDistanceMeters() const; @@ -252,6 +252,8 @@ private: feature::TAltitudes m_altitudes; vector m_traffic; + std::vector m_segmentInfo; + mutable double m_currentTime; // Subroute diff --git a/routing/routing_helpers.cpp b/routing/routing_helpers.cpp index a629900cc9..ca0a32cd59 100644 --- a/routing/routing_helpers.cpp +++ b/routing/routing_helpers.cpp @@ -1,11 +1,13 @@ #include "routing/routing_helpers.hpp" #include "routing/road_point.hpp" +#include "routing/segment.hpp" #include "traffic/traffic_info.hpp" #include "base/stl_helpers.hpp" #include +#include #include namespace @@ -18,6 +20,75 @@ namespace routing using namespace std; using namespace traffic; +void FillSegmentInfo(vector const & segments, vector const & junctions, + Route::TTurns const & turnDirs, Route::TStreets const & streets, + Route::TTimes const & times, shared_ptr const & trafficStash, + vector & segmentInfo) +{ + CHECK_EQUAL(segments.size() + 1, junctions.size(), ()); + CHECK(!turnDirs.empty(), ()); + CHECK(!times.empty(), ()); + + CHECK(std::is_sorted(times.cbegin(), times.cend(), my::LessBy(&Route::TTimeItem::first)), ()); + CHECK(std::is_sorted(turnDirs.cbegin(), turnDirs.cend(), my::LessBy(&turns::TurnItem::m_index)), ()); + CHECK(std::is_sorted(streets.cbegin(), streets.cend(), my::LessBy(&Route::TStreetItem::first)), ()); + + segmentInfo.clear(); + if (segments.empty()) + return; + + segmentInfo.reserve(segments.size()); + // Note. |turnDirs|, |streets| and |times| have point()|junctions| based index. + // On the other hand turns, street names and times are considered for further end of |segments| after conversion + // to |segmentInfo|. It means that street, turn and time information of zero point will be lost after + // conversion to |segmentInfo|. + size_t turnIdx = turnDirs[0].m_index != 0 ? 0 : 1; + size_t streetIdx = (!streets.empty() && streets[0].first != 0) != 0 ? 0 : 1; + size_t timeIdx = times[0].first != 0 ? 0 : 1; + double distFromBeginningMeters = 0.0; + double distFromBeginningMerc = 0.0; + double timeFromBeginningS = 0.0; + + for (size_t i = 0; i < segments.size(); ++i) + { + size_t const segmentEndPointIdx = i + 1; + + turns::TurnItem curTurn; + if (turnIdx != turnDirs.size() && turnDirs[turnIdx].m_index == segmentEndPointIdx) + { + curTurn = turnDirs[turnIdx]; + if (turnIdx + 1 < turnDirs.size()) + ++turnIdx; + } + + string curStreet; + if (!streets.empty()) + { + if (streetIdx != streets.size() && streets[streetIdx].first == segmentEndPointIdx) + { + curStreet = streets[streetIdx].second; + if (streetIdx + 1 < streets.size()) + ++streetIdx; + } + } + + if (timeIdx != times.size() && times[timeIdx].first <= segmentEndPointIdx) + { + timeFromBeginningS = times[timeIdx].second; + ++timeIdx; + } + + distFromBeginningMeters += + MercatorBounds::DistanceOnEarth(junctions[i].GetPoint(), junctions[i + 1].GetPoint()); + distFromBeginningMerc += junctions[i].GetPoint().Length(junctions[i + 1].GetPoint()); + + segmentInfo.emplace_back( + segments[i], curTurn, junctions[i + 1], curStreet, distFromBeginningMeters, + distFromBeginningMerc, timeFromBeginningS, + trafficStash ? trafficStash->GetSpeedGroup(segments[i]) : traffic::SpeedGroup::Unknown); + } +} + void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, shared_ptr const & trafficStash, my::Cancellable const & cancellable, bool hasAltitude, @@ -37,7 +108,8 @@ void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, vector segments; engine.Generate(graph, path, cancellable, turnsDir, streetNames, junctions, segments); - CHECK_EQUAL(segments.size() + 1, junctions.size(), ()); + CHECK_EQUAL(path.size(), junctions.size(), ()); + if (cancellable.IsCancelled()) return; @@ -49,13 +121,14 @@ void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, return; } - CHECK(std::is_sorted(times.cbegin(), times.cend(), my::LessBy(&Route::TTimeItem::first)), ()); - CHECK(std::is_sorted(turnsDir.cbegin(), turnsDir.cend(), my::LessBy(&turns::TurnItem::m_index)), ()); - CHECK(std::is_sorted(streetNames.cbegin(), streetNames.cend(), my::LessBy(&Route::TStreetItem::first)), ()); + vector segmentInfo; + FillSegmentInfo(segments, junctions, turnsDir, streetNames, times, trafficStash, segmentInfo); + CHECK_EQUAL(segmentInfo.size(), segments.size(), ()); + route.SetSegmentInfo(move(segmentInfo)); // @TODO(bykoianko) If the start and the finish of a route lies on the same road segment // engine->Generate() fills with empty vectors |times|, |turnsDir|, |junctions| and |segments|. - // It's not correct and should be fixed. It's necessary to work corrrectly with such routes. + // It's not correct and should be fixed. It's necessary to work correctly with such routes. vector routeGeometry; JunctionsToPoints(junctions, routeGeometry); diff --git a/routing/routing_helpers.hpp b/routing/routing_helpers.hpp index 42b7364ec4..b6820aa4b1 100644 --- a/routing/routing_helpers.hpp +++ b/routing/routing_helpers.hpp @@ -29,6 +29,11 @@ bool IsRoad(TTypes const & types) BicycleModel::AllLimitsInstance().HasRoadType(types); } +void FillSegmentInfo(vector const & segments, vector const & junctions, + Route::TTurns const & turnDirs, Route::TStreets const & streets, + Route::TTimes const & times, shared_ptr const & trafficStash, + vector & segmentInfo); + void ReconstructRoute(IDirectionsEngine & engine, RoadGraphBase const & graph, shared_ptr const & trafficStash, my::Cancellable const & cancellable, bool hasAltitude,