diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp index 620acb6310..5766b57701 100644 --- a/drape_frontend/route_renderer.cpp +++ b/drape_frontend/route_renderer.cpp @@ -56,6 +56,8 @@ uint32_t const kPreviewPointsCount = 512; double const kPreviewAnimationSpeed = 3.0; double const kPreviewAnimationScale = 0.3; +double const kInvalidDistance = -1.0; + void InterpolateByZoom(drape_ptr const & subroute, ScreenBase const & screen, float & halfWidth, double & zoom) { @@ -236,7 +238,7 @@ dp::Color GetOutlineColor(drape_ptr const & subroute) } // namespace RouteRenderer::RouteRenderer(PreviewPointsRequestCallback && previewPointsRequest) - : m_distanceFromBegin(0.0) + : m_distanceFromBegin(kInvalidDistance) , m_followingEnabled(false) , m_previewPointsRequest(std::move(previewPointsRequest)) , m_waitForPreviewRenderData(false) @@ -265,8 +267,10 @@ void RouteRenderer::UpdateRoute(ScreenBase const & screen, CacheRouteArrowsCallb } // Calculate arrow borders. - auto newArrowBorders = CalculateArrowBorders(screen, halfWidth, routeData, - m_followingEnabled ? m_distanceFromBegin : -1.0f); + double dist = kInvalidDistance; + if (m_followingEnabled) + dist = m_distanceFromBegin - routeData->m_subroute->m_baseDistance; + auto newArrowBorders = CalculateArrowBorders(screen, halfWidth, routeData, dist); if (newArrowBorders.empty()) { // Clear arrows. @@ -383,7 +387,9 @@ void RouteRenderer::RenderRouteData(drape_ptr const & routeData, float const currentHalfWidth = m_routeAdditional[routeData->m_subrouteId].m_currentHalfWidth; float const screenHalfWidth = static_cast(currentHalfWidth * screen.GetScale()); - float const dist = m_followingEnabled ? static_cast(m_distanceFromBegin) : -1.0f; + float dist = static_cast(kInvalidDistance); + if (m_followingEnabled) + dist = static_cast(m_distanceFromBegin - routeData->m_subroute->m_baseDistance); dp::GLState const & state = routeData->m_renderProperty.m_state; auto const & subroute = routeData->m_subroute; @@ -561,7 +567,7 @@ void RouteRenderer::ClearRouteData() void RouteRenderer::Clear() { ClearRouteData(); - m_distanceFromBegin = 0.0; + m_distanceFromBegin = kInvalidDistance; } void RouteRenderer::ClearGLDependentResources() diff --git a/drape_frontend/route_shape.hpp b/drape_frontend/route_shape.hpp index 36c151d254..4647341c20 100644 --- a/drape_frontend/route_shape.hpp +++ b/drape_frontend/route_shape.hpp @@ -63,14 +63,16 @@ struct Subroute df::ColorConstant m_color; std::vector m_turns; std::vector m_traffic; + double m_baseDistance = 0.0; df::RoutePattern m_pattern; Subroute() = default; Subroute(m2::PolylineD const & polyline, df::ColorConstant color, std::vector const & turns, std::vector const & traffic, - df::RoutePattern pattern = df::RoutePattern()) - : m_polyline(polyline), m_color(color), m_turns(turns), m_traffic(traffic), m_pattern(pattern) + double baseDistance, df::RoutePattern pattern = df::RoutePattern()) + : m_polyline(polyline), m_color(color), m_turns(turns), m_traffic(traffic) + , m_baseDistance(baseDistance), m_pattern(pattern) {} }; diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index b7dae1803c..be5b36daf2 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -40,6 +40,35 @@ namespace char const kRouterTypeKey[] = "router"; double const kRouteScaleMultiplier = 1.5; + +void FillTurnsDistancesForRendering(std::vector const & segments, + std::vector & turns) +{ + using namespace routing::turns; + turns.clear(); + turns.reserve(segments.size()); + for (auto const & s : segments) + { + auto const & t = s.m_turn; + // We do not render some of turn directions. + if (t.m_turn == TurnDirection::NoTurn || t.m_turn == TurnDirection::StartAtEndOfStreet || + t.m_turn == TurnDirection::StayOnRoundAbout || t.m_turn == TurnDirection::TakeTheExit || + t.m_turn == TurnDirection::ReachedYourDestination || t.m_turn == TurnDirection::Count) + { + continue; + } + turns.push_back(s.m_distFromBeginningMerc); + } +} + +void FillTrafficForRendering(std::vector const & segments, + std::vector & traffic) +{ + traffic.clear(); + traffic.reserve(segments.size()); + for (auto const & s : segments) + traffic.push_back(s.m_traffic); +} } // namespace namespace marketing @@ -126,7 +155,6 @@ void RoutingManager::OnRebuildRouteReady(Route const & route, IRouter::ResultCod if (code != IRouter::NoError) return; - RemoveRoute(false /* deactivateFollowing */); InsertRoute(route); CallRouteBuilded(code, storage::TCountriesVec()); } @@ -210,12 +238,12 @@ void RoutingManager::SetRouterImpl(routing::RouterType type) void RoutingManager::RemoveRoute(bool deactivateFollowing) { - if (m_drapeEngine != nullptr) - { - for (auto const & subrouteId : m_drapeSubroutes) - m_drapeEngine->RemoveSubroute(subrouteId, deactivateFollowing); - m_drapeSubroutes.clear(); - } + if (m_drapeEngine == nullptr) + return; + + for (auto const & subrouteId : m_drapeSubroutes) + m_drapeEngine->RemoveSubroute(subrouteId, deactivateFollowing); + m_drapeSubroutes.clear(); } void RoutingManager::InsertRoute(routing::Route const & route) @@ -223,43 +251,71 @@ void RoutingManager::InsertRoute(routing::Route const & route) if (m_drapeEngine == nullptr) return; - if (route.GetPoly().GetSize() < 2) - { - LOG(LWARNING, ("Invalid track - only", route.GetPoly().GetSize(), "point(s).")); - return; - } + // TODO: Now we always update whole route, so we need to remove previous one. + RemoveRoute(false /* deactivateFollowing */); - auto subroute = make_unique_dp(); - subroute->m_polyline = route.GetPoly(); - switch (m_currentRouterType) + std::vector segments; + std::vector points; + double distance = 0.0; + for (size_t subrouteIndex = 0; subrouteIndex < route.GetSubrouteCount(); subrouteIndex++) { - case RouterType::Vehicle: - subroute->m_routeType = df::RouteType::Car; - subroute->m_color = df::kRouteColor; - subroute->m_traffic = route.GetTraffic(); - route.GetTurnsDistances(subroute->m_turns); - break; - case RouterType::Pedestrian: - subroute->m_routeType = df::RouteType::Pedestrian; - subroute->m_color = df::kRoutePedestrian; - subroute->m_pattern = df::RoutePattern(4.0, 2.0); - break; - case RouterType::Bicycle: - subroute->m_routeType = df::RouteType::Bicycle; - subroute->m_color = df::kRouteBicycle; - subroute->m_pattern = df::RoutePattern(8.0, 2.0); - route.GetTurnsDistances(subroute->m_turns); - break; - case RouterType::Taxi: - subroute->m_routeType = df::RouteType::Taxi; - subroute->m_color = df::kRouteColor; - subroute->m_traffic = route.GetTraffic(); - route.GetTurnsDistances(subroute->m_turns); - break; - default: ASSERT(false, ("Unknown router type")); - } + route.GetSubrouteInfo(subrouteIndex, segments); + Route::SubrouteAttrs attrs; + route.GetSubrouteAttrs(subrouteIndex, attrs); - m_drapeSubroutes.push_back(m_drapeEngine->AddSubroute(std::move(subroute))); + // Fill points. + double const currentBaseDistance = distance; + points.clear(); + points.reserve(segments.size() + 1); + points.push_back(attrs.GetStart().GetPoint()); + for (auto const & s : segments) + { + points.push_back(s.m_junction.GetPoint()); + distance += s.m_distFromBeginningMerc; + } + if (points.size() < 2) + { + LOG(LWARNING, ("Invalid subroute - only", points.size(), "point(s).")); + continue; + } + + auto subroute = make_unique_dp(); + subroute->m_polyline = m2::PolylineD(points); + subroute->m_baseDistance = currentBaseDistance; + switch (m_currentRouterType) + { + case RouterType::Vehicle: + subroute->m_routeType = df::RouteType::Car; + subroute->m_color = df::kRouteColor; + FillTrafficForRendering(segments, subroute->m_traffic); + FillTurnsDistancesForRendering(segments, subroute->m_turns); + break; + case RouterType::Pedestrian: + subroute->m_routeType = df::RouteType::Pedestrian; + subroute->m_color = df::kRoutePedestrian; + subroute->m_pattern = df::RoutePattern(4.0, 2.0); + break; + case RouterType::Bicycle: + subroute->m_routeType = df::RouteType::Bicycle; + subroute->m_color = df::kRouteBicycle; + subroute->m_pattern = df::RoutePattern(8.0, 2.0); + FillTurnsDistancesForRendering(segments, subroute->m_turns); + break; + case RouterType::Taxi: + subroute->m_routeType = df::RouteType::Taxi; + subroute->m_color = df::kRouteColor; + FillTrafficForRendering(segments, subroute->m_traffic); + FillTurnsDistancesForRendering(segments, subroute->m_turns); + break; + default: ASSERT(false, ("Unknown router type")); + } + + auto const subrouteId = m_drapeEngine->AddSubroute(std::move(subroute)); + m_drapeSubroutes.push_back(subrouteId); + + // TODO: we will send subrouteId to routing subsystem when we can partly update route. + //route.SetSubrouteUid(subrouteIndex, static_cast(subrouteId)); + } } void RoutingManager::FollowRoute() diff --git a/routing/route.hpp b/routing/route.hpp index 9d7b6731a8..5409ff4e4c 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -78,6 +78,7 @@ public: class SubrouteAttrs final { public: + SubrouteAttrs() = default; SubrouteAttrs(Junction const & start, Junction const & finish) : m_start(start), m_finish(finish) {