From 03b3412d02a4b7c6e342f02b3e58d419b52dbe3a Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Fri, 2 Jun 2017 19:43:22 +0300 Subject: [PATCH] Multiple route renderer --- android/jni/com/mapswithme/maps/Framework.cpp | 6 +- drape/drape_global.hpp | 4 + drape_frontend/backend_renderer.cpp | 36 +- drape_frontend/drape_engine.cpp | 27 +- drape_frontend/drape_engine.hpp | 18 +- drape_frontend/frontend_renderer.cpp | 98 ++-- drape_frontend/frontend_renderer.hpp | 2 + drape_frontend/message.hpp | 6 +- drape_frontend/message_subclasses.hpp | 119 ++--- drape_frontend/route_builder.cpp | 51 +- drape_frontend/route_builder.hpp | 26 +- drape_frontend/route_renderer.cpp | 491 +++++++++--------- drape_frontend/route_renderer.hpp | 58 ++- drape_frontend/route_shape.cpp | 141 +++-- drape_frontend/route_shape.hpp | 78 +-- iphone/Maps/Core/Routing/MWMRouter.mm | 4 +- map/place_page_info.cpp | 6 + map/place_page_info.hpp | 1 + map/routing_manager.cpp | 122 ++++- map/routing_manager.hpp | 21 +- 20 files changed, 637 insertions(+), 678 deletions(-) diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index f91f3c5e5e..7a9ae5d835 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -1146,14 +1146,16 @@ Java_com_mapswithme_maps_Framework_nativeGetBestRouter(JNIEnv * env, jclass, jdo JNIEXPORT void JNICALL Java_com_mapswithme_maps_Framework_nativeSetRouteStartPoint(JNIEnv * env, jclass, jdouble lat, jdouble lon, jboolean valid) { - frm()->GetRoutingManager().SetRouteStartPoint(m2::PointD(MercatorBounds::FromLatLon(lat, lon)), + frm()->GetRoutingManager().SetRouteStartPoint(frm()->GetBookmarkManager(), + m2::PointD(MercatorBounds::FromLatLon(lat, lon)), static_cast(valid)); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_Framework_nativeSetRouteEndPoint(JNIEnv * env, jclass, jdouble lat, jdouble lon, jboolean valid) { - frm()->GetRoutingManager().SetRouteFinishPoint(m2::PointD(MercatorBounds::FromLatLon(lat, lon)), + frm()->GetRoutingManager().SetRouteFinishPoint(frm()->GetBookmarkManager(), + m2::PointD(MercatorBounds::FromLatLon(lat, lon)), static_cast(valid)); } diff --git a/drape/drape_global.hpp b/drape/drape_global.hpp index 8511bd8cf4..628714e2e2 100644 --- a/drape/drape_global.hpp +++ b/drape/drape_global.hpp @@ -4,6 +4,8 @@ #include "base/assert.hpp" +#include + namespace dp { enum ApiVersion @@ -60,6 +62,8 @@ enum LineJoin RoundJoin = 1, }; +using DrapeID = uint64_t; + struct FontDecl { FontDecl() = default; diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index d42f4fb08e..5f4bc53bb2 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -45,17 +45,12 @@ BackendRenderer::BackendRenderer(Params && params) m_routeBuilder = make_unique_dp([this](drape_ptr && routeData) { m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(move(routeData)), - MessagePriority::Normal); - }, [this](drape_ptr && routeSignData) - { - m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(move(routeSignData)), + make_unique_dp(std::move(routeData)), MessagePriority::Normal); }, [this](drape_ptr && routeArrowsData) { m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(move(routeArrowsData)), + make_unique_dp(std::move(routeArrowsData)), MessagePriority::Normal); }); @@ -271,36 +266,31 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } - case Message::AddRoute: + case Message::AddRouteSegment: { - ref_ptr msg = message; - m_routeBuilder->Build(msg->GetRoutePolyline(), msg->GetTurns(), msg->GetColor(), - msg->GetTraffic(), msg->GetPattern(), m_texMng, msg->GetRecacheId()); - break; - } - - case Message::CacheRouteSign: - { - ref_ptr msg = message; - m_routeBuilder->BuildSign(msg->GetPosition(), msg->IsStart(), msg->IsValid(), m_texMng, msg->GetRecacheId()); + ref_ptr msg = message; + m_routeBuilder->Build(msg->GetSegmentId(), msg->GetRouteSegment(), m_texMng, + msg->GetRecacheId()); break; } case Message::CacheRouteArrows: { ref_ptr msg = message; - m_routeBuilder->BuildArrows(msg->GetRouteIndex(), msg->GetBorders(), m_texMng, msg->GetRecacheId()); + m_routeBuilder->BuildArrows(msg->GetSegmentId(), msg->GetBorders(), m_texMng, + msg->GetRecacheId()); break; } - case Message::RemoveRoute: + case Message::RemoveRouteSegment: { - ref_ptr msg = message; + ref_ptr msg = message; m_routeBuilder->ClearRouteCache(); // We have to resend the message to FR, because it guaranties that - // RemoveRouteMessage will be processed after FlushRouteMessage. + // RemoveRouteSegment will be processed after FlushRouteMessage. m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(msg->NeedDeactivateFollowing()), + make_unique_dp( + msg->GetSegmentId(), msg->NeedDeactivateFollowing()), MessagePriority::Normal); break; } diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 3a0e9069a5..14d2eb5b5b 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -257,6 +257,13 @@ void DrapeEngine::RecacheMapShapes() MessagePriority::Normal); } +dp::DrapeID DrapeEngine::GenerateDrapeID() +{ + std::lock_guard lock(m_drapeIdGeneratorMutex); + ++m_drapeIdGenerator; + return m_drapeIdGenerator; +} + void DrapeEngine::RecacheGui(bool needResetOldGui) { m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, @@ -414,20 +421,19 @@ bool DrapeEngine::GetMyPosition(m2::PointD & myPosition) return hasPosition; } -void DrapeEngine::AddRoute(m2::PolylineD const & routePolyline, std::vector const & turns, - df::ColorConstant color, std::vector const & traffic, - df::RoutePattern pattern) +dp::DrapeID DrapeEngine::AddRouteSegment(drape_ptr && segment) { + dp::DrapeID const id = GenerateDrapeID(); m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(routePolyline, turns, - color, traffic, pattern), + make_unique_dp(id, std::move(segment)), MessagePriority::Normal); + return id; } -void DrapeEngine::RemoveRoute(bool deactivateFollowing) +void DrapeEngine::RemoveRouteSegment(dp::DrapeID segmentId, bool deactivateFollowing) { m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(deactivateFollowing), + make_unique_dp(segmentId, deactivateFollowing), MessagePriority::Normal); } @@ -438,13 +444,6 @@ void DrapeEngine::DeactivateRouteFollowing() MessagePriority::Normal); } -void DrapeEngine::SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid) -{ - m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(position, isStart, isValid), - MessagePriority::Normal); -} - void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info) { m_widgetsLayout = std::move(info); diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index b277ac5bfe..10c0dd8cb6 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -12,6 +12,7 @@ #include "drape_frontend/selection_shape.hpp" #include "drape_frontend/threads_commutator.hpp" +#include "drape/drape_global.hpp" #include "drape/pointers.hpp" #include "drape/texture_manager.hpp" #include "drape/viewport.hpp" @@ -27,6 +28,7 @@ #include "base/strings_bundle.hpp" #include +#include #include namespace dp @@ -139,7 +141,8 @@ public: void UpdateMapStyle(); void SetCompassInfo(location::CompassInfo const & info); - void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo); + void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, + location::RouteMatchingInfo const & routeInfo); void SwitchMyPositionNextMode(); void LoseLocation(); void StopLocationFollow(); @@ -156,13 +159,11 @@ public: bool GetMyPosition(m2::PointD & myPosition); SelectionShape::ESelectedObject GetSelectedObject(); - void AddRoute(m2::PolylineD const & routePolyline, std::vector const & turns, - df::ColorConstant color, std::vector const & traffic, - df::RoutePattern pattern = df::RoutePattern()); - void RemoveRoute(bool deactivateFollowing); + dp::DrapeID AddRouteSegment(drape_ptr && segment); + void RemoveRouteSegment(dp::DrapeID segmentId, bool deactivateFollowing); + void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom); void DeactivateRouteFollowing(); - void SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid); void SetWidgetLayout(gui::TWidgetsLayoutInfo && info); @@ -221,6 +222,8 @@ private: void RecacheGui(bool needResetOldGui); void RecacheMapShapes(); + dp::DrapeID GenerateDrapeID(); + drape_ptr m_frontend; drape_ptr m_backend; drape_ptr m_threadCommutator; @@ -240,6 +243,9 @@ private: bool m_choosePositionMode = false; bool m_kineticScrollEnabled = true; + std::mutex m_drapeIdGeneratorMutex; + dp::DrapeID m_drapeIdGenerator = 0; + friend class DrapeApi; }; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 6611c5e6d1..8d93e0bbe7 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -464,69 +464,54 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) { ref_ptr msg = message; drape_ptr routeData = msg->AcceptRouteData(); - - if (routeData->m_recacheId > 0 && routeData->m_recacheId < m_lastRecacheRouteId) + if (!CheckRouteRecaching(make_ref(routeData))) break; - m2::PointD const finishPoint = routeData->m_sourcePolyline.Back(); - m_routeRenderer->SetRouteData(std::move(routeData), make_ref(m_gpuProgramManager)); + m_routeRenderer->AddRouteData(std::move(routeData), make_ref(m_gpuProgramManager)); + // Here we have to recache route arrows. m_routeRenderer->UpdateRoute(m_userEventStream.GetCurrentScreen(), std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2)); - if (!m_routeRenderer->GetFinishPoint()) - { - m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(finishPoint, false /* isStart */, - true /* isValid */), - MessagePriority::High); - } - if (m_pendingFollowRoute != nullptr) { - FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d, + FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, + m_pendingFollowRoute->m_preferredZoomLevelIn3d, m_pendingFollowRoute->m_enableAutoZoom); m_pendingFollowRoute.reset(); } break; } - case Message::FlushRouteSign: - { - ref_ptr msg = message; - drape_ptr routeSignData = msg->AcceptRouteSignData(); - - if (routeSignData->m_recacheId > 0 && routeSignData->m_recacheId < m_lastRecacheRouteId) - break; - - m_routeRenderer->SetRouteSign(std::move(routeSignData), make_ref(m_gpuProgramManager)); - break; - } - case Message::FlushRouteArrows: { ref_ptr msg = message; drape_ptr routeArrowsData = msg->AcceptRouteArrowsData(); - - if (routeArrowsData->m_recacheId > 0 && routeArrowsData->m_recacheId < m_lastRecacheRouteId) - break; - - m_routeRenderer->SetRouteArrows(std::move(routeArrowsData), make_ref(m_gpuProgramManager)); + if (CheckRouteRecaching(make_ref(routeArrowsData))) + { + m_routeRenderer->AddRouteArrowsData(std::move(routeArrowsData), + make_ref(m_gpuProgramManager)); + } break; } - case Message::RemoveRoute: + case Message::RemoveRouteSegment: { - ref_ptr msg = message; - m_routeRenderer->Clear(); - ++m_lastRecacheRouteId; + ref_ptr msg = message; if (msg->NeedDeactivateFollowing()) { + m_routeRenderer->SetFollowingEnabled(false); + m_routeRenderer->Clear(); + ++m_lastRecacheRouteId; m_myPositionController->DeactivateRouting(); m_overlayTree->SetFollowingMode(false); if (m_enablePerspectiveInNavigation) DisablePerspective(); } + else + { + m_routeRenderer->RemoveRouteData(msg->GetSegmentId()); + } break; } @@ -536,7 +521,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) // After night style switching or drape engine reinitialization FrontendRenderer can // receive FollowRoute message before FlushRoute message, so we need to postpone its processing. - if (m_routeRenderer->GetRouteData() == nullptr) + if (m_routeRenderer->GetRouteData().empty()) { m_pendingFollowRoute = my::make_unique(msg->GetPreferredZoomLevel(), msg->GetPreferredZoomLevelIn3d(), @@ -817,35 +802,15 @@ void FrontendRenderer::UpdateGLResources() { ++m_lastRecacheRouteId; - // Invalidate route. - if (m_routeRenderer->GetStartPoint()) + for (auto const & routeData : m_routeRenderer->GetRouteData()) { - m2::PointD const & position = m_routeRenderer->GetStartPoint()->m_position; - m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(position, true /* isStart */, - true /* isValid */, m_lastRecacheRouteId), - MessagePriority::High); - } - - if (m_routeRenderer->GetFinishPoint()) - { - m2::PointD const & position = m_routeRenderer->GetFinishPoint()->m_position; - m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(position, false /* isStart */, - true /* isValid */, m_lastRecacheRouteId), - MessagePriority::High); - } - - auto const & routeData = m_routeRenderer->GetRouteData(); - if (routeData != nullptr) - { - auto recacheRouteMsg = make_unique_dp(routeData->m_sourcePolyline, routeData->m_sourceTurns, - routeData->m_color, routeData->m_traffic, - routeData->m_pattern, m_lastRecacheRouteId); - m_routeRenderer->ClearGLDependentResources(); - m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, std::move(recacheRouteMsg), + auto msg = make_unique_dp(routeData->m_segmentId, + std::move(routeData->m_segment), + m_lastRecacheRouteId); + m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, std::move(msg), MessagePriority::Normal); } + m_routeRenderer->ClearRouteData(); m_trafficRenderer->ClearGLDependentResources(); @@ -872,6 +837,16 @@ void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLeve AddUserEvent(make_unique_dp(true /* isAutoPerspective */)); m_overlayTree->SetFollowingMode(true); + + m_routeRenderer->SetFollowingEnabled(true); +} + +bool FrontendRenderer::CheckRouteRecaching(ref_ptr routeData) +{ + if (routeData->m_recacheId < 0) + return true; + + return routeData->m_recacheId >= m_lastRecacheRouteId; } void FrontendRenderer::InvalidateRect(m2::RectD const & gRect) @@ -1187,7 +1162,6 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) { StencilWriterGuard guard(make_ref(m_postprocessRenderer)); RenderUserMarksLayer(modelView); - m_routeRenderer->RenderRouteSigns(modelView, make_ref(m_gpuProgramManager), m_generalUniforms); } m_myPositionController->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager), diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 1bf7750189..0ab7728a5f 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -209,6 +209,8 @@ private: void RemoveRenderGroupsLater(TRenderGroupRemovePredicate const & predicate); void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom); + bool CheckRouteRecaching(ref_ptr routeData); + void InvalidateRect(m2::RectD const & gRect); bool CheckTileGenerations(TileKey const & tileKey); void UpdateCanBeDeletedStatus(); diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 8497ac901f..a18c6fa4ac 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -36,12 +36,10 @@ public: SelectObject, GetSelectedObject, GetMyPosition, - AddRoute, - CacheRouteSign, + AddRouteSegment, + RemoveRouteSegment, CacheRouteArrows, - RemoveRoute, FlushRoute, - FlushRouteSign, FlushRouteArrows, FollowRoute, DeactivateRouteFollowing, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index e162819127..f9e7f2700a 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -602,109 +602,72 @@ private: bool & m_hasPosition; }; -class AddRouteMessage : public Message +class AddRouteSegmentMessage : public Message { public: - AddRouteMessage(m2::PolylineD const & routePolyline, vector const & turns, - df::ColorConstant color, vector const & traffic, - df::RoutePattern const & pattern) - : AddRouteMessage(routePolyline, turns, color, traffic, pattern, -1 /* invalid recache id */) + AddRouteSegmentMessage(dp::DrapeID segmentId, drape_ptr && segment) + : AddRouteSegmentMessage(segmentId, std::move(segment), -1 /* invalid recache id */) {} - AddRouteMessage(m2::PolylineD const & routePolyline, vector const & turns, - df::ColorConstant color, vector const & traffic, - df::RoutePattern const & pattern, int recacheId) - : m_routePolyline(routePolyline) - , m_color(color) - , m_turns(turns) - , m_pattern(pattern) - , m_traffic(traffic) + AddRouteSegmentMessage(dp::DrapeID segmentId, drape_ptr && segment, + int recacheId) + : m_segmentId(segmentId) + , m_segment(std::move(segment)) , m_recacheId(recacheId) {} - Type GetType() const override { return Message::AddRoute; } + Type GetType() const override { return Message::AddRouteSegment; } - m2::PolylineD const & GetRoutePolyline() { return m_routePolyline; } - df::ColorConstant GetColor() const { return m_color; } - vector const & GetTurns() const { return m_turns; } - df::RoutePattern const & GetPattern() const { return m_pattern; } - vector const & GetTraffic() const { return m_traffic; } + dp::DrapeID GetSegmentId() const { return m_segmentId; }; + drape_ptr && GetRouteSegment() { return std::move(m_segment); } int GetRecacheId() const { return m_recacheId; } private: - m2::PolylineD m_routePolyline; - df::ColorConstant m_color; - vector m_turns; - df::RoutePattern m_pattern; - vector m_traffic; - int const m_recacheId; -}; - -class CacheRouteSignMessage : public Message -{ -public: - CacheRouteSignMessage(m2::PointD const & pos, bool isStart, bool isValid) - : CacheRouteSignMessage(pos, isStart, isValid, -1 /* invalid recache id */) - {} - - CacheRouteSignMessage(m2::PointD const & pos, bool isStart, bool isValid, int recacheId) - : m_position(pos) - , m_isStart(isStart) - , m_isValid(isValid) - , m_recacheId(recacheId) - {} - - Type GetType() const override { return Message::CacheRouteSign; } - - m2::PointD const & GetPosition() const { return m_position; } - bool IsStart() const { return m_isStart; } - bool IsValid() const { return m_isValid; } - int GetRecacheId() const { return m_recacheId; } - -private: - m2::PointD const m_position; - bool const m_isStart; - bool const m_isValid; + dp::DrapeID m_segmentId; + drape_ptr m_segment; int const m_recacheId; }; class CacheRouteArrowsMessage : public Message { public: - CacheRouteArrowsMessage(int routeIndex, vector const & borders) - : CacheRouteArrowsMessage(routeIndex, borders, -1 /* invalid recache id */) + CacheRouteArrowsMessage(dp::DrapeID segmentId, std::vector const & borders) + : CacheRouteArrowsMessage(segmentId, borders, -1 /* invalid recache id */) {} - CacheRouteArrowsMessage(int routeIndex, vector const & borders, int recacheId) - : m_routeIndex(routeIndex) + CacheRouteArrowsMessage(dp::DrapeID segmentId, std::vector const & borders, + int recacheId) + : m_segmentId(segmentId) , m_borders(borders) , m_recacheId(recacheId) {} Type GetType() const override { return Message::CacheRouteArrows; } - - int GetRouteIndex() const { return m_routeIndex; } - vector const & GetBorders() const { return m_borders; } + dp::DrapeID GetSegmentId() const { return m_segmentId; } + std::vector const & GetBorders() const { return m_borders; } int GetRecacheId() const { return m_recacheId; } private: - int m_routeIndex; - vector m_borders; + dp::DrapeID m_segmentId; + std::vector m_borders; int const m_recacheId; }; -class RemoveRouteMessage : public Message +class RemoveRouteSegmentMessage : public Message { public: - RemoveRouteMessage(bool deactivateFollowing) - : m_deactivateFollowing(deactivateFollowing) + RemoveRouteSegmentMessage(dp::DrapeID segmentId, bool deactivateFollowing) + : m_segmentId(segmentId) + , m_deactivateFollowing(deactivateFollowing) {} - Type GetType() const override { return Message::RemoveRoute; } + Type GetType() const override { return Message::RemoveRouteSegment; } + dp::DrapeID GetSegmentId() const { return m_segmentId; } bool NeedDeactivateFollowing() const { return m_deactivateFollowing; } private: + dp::DrapeID m_segmentId; bool m_deactivateFollowing; }; @@ -712,13 +675,13 @@ class FlushRouteMessage : public Message { public: FlushRouteMessage(drape_ptr && routeData) - : m_routeData(move(routeData)) + : m_routeData(std::move(routeData)) {} Type GetType() const override { return Message::FlushRoute; } - bool IsGLContextDependent() const override { return true; } - drape_ptr && AcceptRouteData() { return move(m_routeData); } + bool IsGLContextDependent() const override { return true; } + drape_ptr && AcceptRouteData() { return std::move(m_routeData); } private: drape_ptr m_routeData; @@ -728,33 +691,17 @@ class FlushRouteArrowsMessage : public Message { public: FlushRouteArrowsMessage(drape_ptr && routeArrowsData) - : m_routeArrowsData(move(routeArrowsData)) + : m_routeArrowsData(std::move(routeArrowsData)) {} Type GetType() const override { return Message::FlushRouteArrows; } - drape_ptr && AcceptRouteArrowsData() { return move(m_routeArrowsData); } + drape_ptr && AcceptRouteArrowsData() { return std::move(m_routeArrowsData); } private: drape_ptr m_routeArrowsData; }; -class FlushRouteSignMessage : public Message -{ -public: - FlushRouteSignMessage(drape_ptr && routeSignData) - : m_routeSignData(move(routeSignData)) - {} - - Type GetType() const override { return Message::FlushRouteSign; } - bool IsGLContextDependent() const override { return true; } - - drape_ptr && AcceptRouteSignData() { return move(m_routeSignData); } - -private: - drape_ptr m_routeSignData; -}; - class UpdateMapStyleMessage : public BaseBlockingMessage { public: diff --git a/drape_frontend/route_builder.cpp b/drape_frontend/route_builder.cpp index 9d13b149f5..3c79e67401 100644 --- a/drape_frontend/route_builder.cpp +++ b/drape_frontend/route_builder.cpp @@ -4,37 +4,28 @@ namespace df { - RouteBuilder::RouteBuilder(TFlushRouteFn const & flushRouteFn, - TFlushRouteSignFn const & flushRouteSignFn, TFlushRouteArrowsFn const & flushRouteArrowsFn) : m_flushRouteFn(flushRouteFn) - , m_flushRouteSignFn(flushRouteSignFn) , m_flushRouteArrowsFn(flushRouteArrowsFn) {} -void RouteBuilder::Build(m2::PolylineD const & routePolyline, vector const & turns, - df::ColorConstant color, vector const & traffic, - df::RoutePattern const & pattern, ref_ptr textures, - int recacheId) +void RouteBuilder::Build(dp::DrapeID segmentId, drape_ptr && segment, + ref_ptr textures, int recacheId) { drape_ptr routeData = make_unique_dp(); - routeData->m_routeIndex = m_routeIndex++; - routeData->m_color = color; - routeData->m_sourcePolyline = routePolyline; - routeData->m_sourceTurns = turns; - routeData->m_traffic = traffic; - routeData->m_pattern = pattern; - routeData->m_pivot = routePolyline.GetLimitRect().Center(); + routeData->m_segmentId = segmentId; + routeData->m_segment = std::move(segment); + routeData->m_pivot = routeData->m_segment->m_polyline.GetLimitRect().Center(); routeData->m_recacheId = recacheId; RouteShape::CacheRoute(textures, *routeData.get()); - m_routeCache.insert(make_pair(routeData->m_routeIndex, routePolyline)); + m_routeCache.insert(std::make_pair(segmentId, routeData->m_segment->m_polyline)); // Flush route geometry. GLFunctions::glFlush(); if (m_flushRouteFn != nullptr) - m_flushRouteFn(move(routeData)); + m_flushRouteFn(std::move(routeData)); } void RouteBuilder::ClearRouteCache() @@ -42,32 +33,15 @@ void RouteBuilder::ClearRouteCache() m_routeCache.clear(); } -void RouteBuilder::BuildSign(m2::PointD const & pos, bool isStart, bool isValid, - ref_ptr textures, int recacheId) -{ - drape_ptr routeSignData = make_unique_dp(); - routeSignData->m_isStart = isStart; - routeSignData->m_position = pos; - routeSignData->m_isValid = isValid; - routeSignData->m_recacheId = recacheId; - if (isValid) - RouteShape::CacheRouteSign(textures, *routeSignData.get()); - - // Flush route sign geometry. - GLFunctions::glFlush(); - - if (m_flushRouteSignFn != nullptr) - m_flushRouteSignFn(move(routeSignData)); -} - -void RouteBuilder::BuildArrows(int routeIndex, vector const & borders, +void RouteBuilder::BuildArrows(dp::DrapeID segmentId, std::vector const & borders, ref_ptr textures, int recacheId) { - auto it = m_routeCache.find(routeIndex); + auto it = m_routeCache.find(segmentId); if (it == m_routeCache.end()) return; drape_ptr routeArrowsData = make_unique_dp(); + routeArrowsData->m_segmentId = segmentId; routeArrowsData->m_pivot = it->second.GetLimitRect().Center(); routeArrowsData->m_recacheId = recacheId; RouteShape::CacheRouteArrows(textures, it->second, borders, *routeArrowsData.get()); @@ -76,7 +50,6 @@ void RouteBuilder::BuildArrows(int routeIndex, vector const & bord GLFunctions::glFlush(); if (m_flushRouteArrowsFn != nullptr) - m_flushRouteArrowsFn(move(routeArrowsData)); + m_flushRouteArrowsFn(std::move(routeArrowsData)); } - -} // namespace df +} // namespace df diff --git a/drape_frontend/route_builder.hpp b/drape_frontend/route_builder.hpp index f229cfd888..2067e96d45 100644 --- a/drape_frontend/route_builder.hpp +++ b/drape_frontend/route_builder.hpp @@ -10,43 +10,33 @@ #include "geometry/polyline2d.hpp" -#include "std/function.hpp" -#include "std/unordered_map.hpp" +#include +#include +#include namespace df { - class RouteBuilder { public: using TFlushRouteFn = function &&)>; - using TFlushRouteSignFn = function &&)>; using TFlushRouteArrowsFn = function &&)>; RouteBuilder(TFlushRouteFn const & flushRouteFn, - TFlushRouteSignFn const & flushRouteSignFn, TFlushRouteArrowsFn const & flushRouteArrowsFn); - void Build(m2::PolylineD const & routePolyline, vector const & turns, - df::ColorConstant color, vector const & traffic, - df::RoutePattern const & pattern, ref_ptr textures, - int recacheId); + void Build(dp::DrapeID segmentId, drape_ptr && segment, + ref_ptr textures, int recacheId); - void BuildArrows(int routeIndex, vector const & borders, + void BuildArrows(dp::DrapeID segmentId, std::vector const & borders, ref_ptr textures, int recacheId); - void BuildSign(m2::PointD const & pos, bool isStart, bool isValid, - ref_ptr textures, int recacheId); - void ClearRouteCache(); private: TFlushRouteFn m_flushRouteFn; - TFlushRouteSignFn m_flushRouteSignFn; TFlushRouteArrowsFn m_flushRouteArrowsFn; - int m_routeIndex = 0; - unordered_map m_routeCache; + std::unordered_map m_routeCache; }; - -} // namespace df +} // namespace df diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp index 1a681afc6d..872cdfd034 100644 --- a/drape_frontend/route_renderer.cpp +++ b/drape_frontend/route_renderer.cpp @@ -8,14 +8,14 @@ #include "drape/utils/projection.hpp" #include "drape/vertex_array_buffer.hpp" -#include "indexer/map_style_reader.hpp" #include "indexer/scales.hpp" #include "base/logging.hpp" +#include + namespace df { - std::string const kRouteColor = "Route"; std::string const kRouteOutlineColor = "RouteOutline"; std::string const kRoutePedestrian = "RoutePedestrian"; @@ -23,8 +23,7 @@ std::string const kRouteBicycle = "RouteBicycle"; namespace { - -float const kHalfWidthInPixelVehicle[] = +float const kHalfWidthInPixelCar[] = { // 1 2 3 4 5 6 7 8 9 10 1.0f, 1.0f, 1.5f, 1.5f, 1.5f, 2.0f, 2.0f, 2.0f, 2.5f, 2.5f, @@ -43,31 +42,31 @@ float const kHalfWidthInPixelOthers[] = int const kArrowAppearingZoomLevel = 14; int const kInvalidGroup = -1; -void ClipBorders(vector & borders) +void ClipBorders(std::vector & borders) { auto invalidBorders = [](ArrowBorders const & borders) { return borders.m_groupIndex == kInvalidGroup; }; - borders.erase(remove_if(borders.begin(), borders.end(), invalidBorders), borders.end()); + borders.erase(std::remove_if(borders.begin(), borders.end(), invalidBorders), borders.end()); } -void MergeAndClipBorders(vector & borders) +void MergeAndClipBorders(std::vector & borders) { - // initial clipping + // Initial clipping. ClipBorders(borders); if (borders.empty()) return; - // mark groups + // Mark groups. for (size_t i = 0; i + 1 < borders.size(); i++) { if (borders[i].m_endDistance >= borders[i + 1].m_startDistance) borders[i + 1].m_groupIndex = borders[i].m_groupIndex; } - // merge groups + // Merge groups. int lastGroup = borders.front().m_groupIndex; size_t lastGroupIndex = 0; for (size_t i = 1; i < borders.size(); i++) @@ -85,17 +84,12 @@ void MergeAndClipBorders(vector & borders) } borders[lastGroupIndex].m_endDistance = borders.back().m_endDistance; - // clip groups + // Clip groups. ClipBorders(borders); } -void BuildBuckets(RouteRenderProperty const & renderProperty, ref_ptr mng) -{ - for (drape_ptr const & bucket : renderProperty.m_buckets) - bucket->GetBuffer()->Build(mng->GetProgram(renderProperty.m_state.GetProgramIndex())); -} - -bool AreEqualArrowBorders(vector const & borders1, vector const & borders2) +bool AreEqualArrowBorders(std::vector const & borders1, + std::vector const & borders2) { if (borders1.size() != borders2.size()) return false; @@ -119,28 +113,105 @@ bool AreEqualArrowBorders(vector const & borders1, vector CalculateArrowBorders(ScreenBase const & screen, float currentHalfWidth, + drape_ptr const & routeData, + double distanceFromBegin) { - return df::GetColorConstant(routeColor == kRouteColor ? kRouteOutlineColor : routeColor); + if (routeData->m_segment->m_turns.empty()) + return {}; + + // Calculate arrow mercator length. + double glbHalfLen = 0.5 * kArrowSize; + double const glbHalfTextureWidth = currentHalfWidth * kArrowHeightFactor * screen.GetScale(); + double const glbHalfTextureLen = glbHalfTextureWidth * kArrowAspect; + if (glbHalfLen < glbHalfTextureLen) + glbHalfLen = glbHalfTextureLen; + + double const glbArrowHead = 2.0 * kArrowHeadSize * glbHalfTextureLen; + double const glbArrowTail = 2.0 * kArrowTailSize * glbHalfTextureLen; + double const glbMinArrowSize = glbArrowHead + glbArrowTail; + + double const kExtendCoef = 1.1; + m2::RectD screenRect = screen.ClipRect(); + screenRect.Scale(kExtendCoef); + + auto const & segment = routeData->m_segment; + + // Calculate arrow borders. + std::vector newArrowBorders; + newArrowBorders.reserve(segment->m_turns.size()); + for (size_t i = 0; i < segment->m_turns.size(); i++) + { + ArrowBorders arrowBorders; + arrowBorders.m_groupIndex = static_cast(i); + arrowBorders.m_startDistance = std::max(0.0, segment->m_turns[i] - glbHalfLen * 0.8); + arrowBorders.m_endDistance = std::min(routeData->m_length, segment->m_turns[i] + glbHalfLen * 1.2); + + if ((arrowBorders.m_endDistance - arrowBorders.m_startDistance) < glbMinArrowSize || + arrowBorders.m_startDistance < distanceFromBegin) + { + continue; + } + + m2::PointD pt = segment->m_polyline.GetPointByDistance(arrowBorders.m_startDistance); + if (screenRect.IsPointInside(pt)) + { + newArrowBorders.push_back(arrowBorders); + continue; + } + + pt = segment->m_polyline.GetPointByDistance(arrowBorders.m_endDistance); + if (screenRect.IsPointInside(pt)) + { + newArrowBorders.push_back(arrowBorders); + continue; + } + } + + // Merge intersected borders and clip them. + MergeAndClipBorders(newArrowBorders); + + // Process head and tail. + for (ArrowBorders & borders : newArrowBorders) + { + borders.m_startDistance += glbArrowTail; + borders.m_endDistance -= glbArrowHead; + } + + return newArrowBorders; } -} // namespace +void BuildBuckets(RouteRenderProperty const & renderProperty, ref_ptr mng) +{ + for (auto const & bucket : renderProperty.m_buckets) + bucket->GetBuffer()->Build(mng->GetProgram(renderProperty.m_state.GetProgramIndex())); +} + +dp::Color GetOutlineColor(drape_ptr const & routeSegment) +{ + if (routeSegment->m_routeType == RouteType::Car || routeSegment->m_routeType == RouteType::Taxi) + return df::GetColorConstant(kRouteOutlineColor); + + return df::GetColorConstant(routeSegment->m_color); +} +} // namespace RouteRenderer::RouteRenderer() : m_distanceFromBegin(0.0) + , m_followingEnabled(false) {} -void RouteRenderer::InterpolateByZoom(ScreenBase const & screen, ColorConstant color, +void RouteRenderer::InterpolateByZoom(drape_ptr const & routeSegment, ScreenBase const & screen, float & halfWidth, double & zoom) const { double const zoomLevel = GetZoomLevel(screen.GetScale()); zoom = trunc(zoomLevel); - int const index = zoom - 1.0; - float const lerpCoef = zoomLevel - zoom; + int const index = static_cast(zoom - 1.0); + float const lerpCoef = static_cast(zoomLevel - zoom); - float const * halfWidthInPixel = kHalfWidthInPixelVehicle; - if (color != kRouteColor) - halfWidthInPixel = kHalfWidthInPixelOthers; + float const * halfWidthInPixel = kHalfWidthInPixelOthers; + if (routeSegment->m_routeType == RouteType::Car || routeSegment->m_routeType == RouteType::Taxi) + halfWidthInPixel = kHalfWidthInPixelCar; if (index < scales::UPPER_STYLE_SCALE) halfWidth = halfWidthInPixel[index] + lerpCoef * (halfWidthInPixel[index + 1] - halfWidthInPixel[index]); @@ -153,272 +224,192 @@ void RouteRenderer::InterpolateByZoom(ScreenBase const & screen, ColorConstant c void RouteRenderer::UpdateRoute(ScreenBase const & screen, TCacheRouteArrowsCallback const & callback) { ASSERT(callback != nullptr, ()); - - if (!m_routeData) - return; - - // Interpolate values by zoom level. - double zoom = 0.0; - InterpolateByZoom(screen, m_routeData->m_color, m_currentHalfWidth, zoom); - - // Update arrows. - if (zoom >= kArrowAppearingZoomLevel && !m_routeData->m_sourceTurns.empty()) + for (auto const & routeData : m_routeData) { - // Calculate arrow mercator length. - double glbHalfLen = 0.5 * kArrowSize; - double const glbHalfTextureWidth = m_currentHalfWidth * kArrowHeightFactor * screen.GetScale(); - double const glbHalfTextureLen = glbHalfTextureWidth * kArrowAspect; - if (glbHalfLen < glbHalfTextureLen) - glbHalfLen = glbHalfTextureLen; + auto & additional = m_routeAdditional[routeData->m_segmentId]; - double const glbArrowHead = 2.0 * kArrowHeadSize * glbHalfTextureLen; - double const glbArrowTail = 2.0 * kArrowTailSize * glbHalfTextureLen; - double const glbMinArrowSize = glbArrowHead + glbArrowTail; + // Interpolate values by zoom level. + double zoom = 0.0; + float halfWidth = 0.0; + InterpolateByZoom(routeData->m_segment, screen, halfWidth, zoom); + additional.m_currentHalfWidth = halfWidth; - double const kExtendCoef = 1.1; - m2::RectD screenRect = screen.ClipRect(); - screenRect.Scale(kExtendCoef); + if (zoom < kArrowAppearingZoomLevel) + { + additional.m_arrowsData.reset(); + additional.m_arrowBorders.clear(); + continue; + } // Calculate arrow borders. - vector newArrowBorders; - newArrowBorders.reserve(m_routeData->m_sourceTurns.size()); - for (size_t i = 0; i < m_routeData->m_sourceTurns.size(); i++) - { - ArrowBorders arrowBorders; - arrowBorders.m_groupIndex = static_cast(i); - arrowBorders.m_startDistance = max(0.0, m_routeData->m_sourceTurns[i] - glbHalfLen * 0.8); - arrowBorders.m_endDistance = min(m_routeData->m_length, m_routeData->m_sourceTurns[i] + glbHalfLen * 1.2); - - if ((arrowBorders.m_endDistance - arrowBorders.m_startDistance) < glbMinArrowSize || - arrowBorders.m_startDistance < m_distanceFromBegin) - continue; - - m2::PointD pt = m_routeData->m_sourcePolyline.GetPointByDistance(arrowBorders.m_startDistance); - if (screenRect.IsPointInside(pt)) - { - newArrowBorders.push_back(arrowBorders); - continue; - } - - pt = m_routeData->m_sourcePolyline.GetPointByDistance(arrowBorders.m_endDistance); - if (screenRect.IsPointInside(pt)) - { - newArrowBorders.push_back(arrowBorders); - continue; - } - } - - // Merge intersected borders and clip them. - MergeAndClipBorders(newArrowBorders); - - // Process head and tail. - for (ArrowBorders & borders : newArrowBorders) - { - borders.m_startDistance += glbArrowTail; - borders.m_endDistance -= glbArrowHead; - } - + auto newArrowBorders = CalculateArrowBorders(screen, halfWidth, routeData, + m_followingEnabled ? m_distanceFromBegin : -1.0f); if (newArrowBorders.empty()) { // Clear arrows. - m_arrowBorders.clear(); - m_routeArrows.reset(); + additional.m_arrowsData.reset(); + additional.m_arrowBorders.clear(); } - else if (!AreEqualArrowBorders(newArrowBorders, m_arrowBorders)) + else if (!AreEqualArrowBorders(newArrowBorders, additional.m_arrowBorders)) { - m_arrowBorders = move(newArrowBorders); - callback(m_routeData->m_routeIndex, m_arrowBorders); + additional.m_arrowBorders = std::move(newArrowBorders); + callback(routeData->m_segmentId, additional.m_arrowBorders); } } +} + +void RouteRenderer::RenderRouteData(drape_ptr const & routeData, + ScreenBase const & screen, bool trafficShown, + ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms) +{ + if (routeData->m_renderProperty.m_buckets.empty()) + return; + + float const currentHalfWidth = m_routeAdditional[routeData->m_segmentId].m_currentHalfWidth; + float const screenHalfWidth = static_cast(currentHalfWidth * screen.GetScale()); + float const dist = m_followingEnabled ? static_cast(m_distanceFromBegin) : -1.0f; + + dp::GLState const & state = routeData->m_renderProperty.m_state; + auto const & segment = routeData->m_segment; + + // Set up uniforms. + dp::UniformValuesStorage uniforms = commonUniforms; + math::Matrix mv = screen.GetModelView(routeData->m_pivot, kShapeCoordScalar); + uniforms.SetMatrix4x4Value("modelView", mv.m_data); + + glsl::vec4 const color = glsl::ToVec4(df::GetColorConstant(segment->m_color)); + uniforms.SetFloatValue("u_color", color.r, color.g, color.b, color.a); + + uniforms.SetFloatValue("u_routeParams", currentHalfWidth, screenHalfWidth, dist, + trafficShown ? 1.0f : 0.0f); + + if (segment->m_pattern.m_isDashed) + { + uniforms.SetFloatValue("u_pattern", + static_cast(screenHalfWidth * segment->m_pattern.m_dashLength), + static_cast(screenHalfWidth * segment->m_pattern.m_gapLength)); + } else { - m_routeArrows.reset(); + glsl::vec4 const outlineColor = glsl::ToVec4(GetOutlineColor(segment)); + uniforms.SetFloatValue("u_outlineColor", outlineColor.r, outlineColor.g, + outlineColor.b, outlineColor.a); } + + // Set up shaders and apply uniforms. + ref_ptr prg = mng->GetProgram(segment->m_pattern.m_isDashed ? + gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM); + prg->Bind(); + dp::ApplyState(state, prg); + dp::ApplyUniforms(uniforms, prg); + + // Render buckets. + for (auto const & bucket : routeData->m_renderProperty.m_buckets) + bucket->Render(state.GetDrawAsLine()); +} + +void RouteRenderer::RenderRouteArrowData(dp::DrapeID segmentId, RouteAdditional const & routeAdditional, + ScreenBase const & screen, ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms) +{ + if (routeAdditional.m_arrowsData == nullptr || + routeAdditional.m_arrowsData->m_renderProperty.m_buckets.empty()) + { + return; + } + + float const currentHalfWidth = m_routeAdditional[segmentId].m_currentHalfWidth; + dp::GLState const & state = routeAdditional.m_arrowsData->m_renderProperty.m_state; + + // Set up shaders and apply common uniforms. + dp::UniformValuesStorage uniforms = commonUniforms; + math::Matrix mv = screen.GetModelView(routeAdditional.m_arrowsData->m_pivot, + kShapeCoordScalar); + uniforms.SetMatrix4x4Value("modelView", mv.m_data); + uniforms.SetFloatValue("u_arrowHalfWidth", static_cast(currentHalfWidth * kArrowHeightFactor)); + uniforms.SetFloatValue("u_opacity", 1.0f); + + ref_ptr prg = mng->GetProgram(gpu::ROUTE_ARROW_PROGRAM); + prg->Bind(); + dp::ApplyState(state, prg); + dp::ApplyUniforms(uniforms, prg); + for (auto const & bucket : routeAdditional.m_arrowsData->m_renderProperty.m_buckets) + bucket->Render(state.GetDrawAsLine()); } void RouteRenderer::RenderRoute(ScreenBase const & screen, bool trafficShown, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms) { - if (!m_routeData || m_routeData->m_route.m_buckets.empty()) + if (m_routeData.empty()) return; // Render route. - { - dp::GLState const & state = m_routeData->m_route.m_state; - - // Set up uniforms. - dp::UniformValuesStorage uniforms = commonUniforms; - math::Matrix mv = screen.GetModelView(m_routeData->m_pivot, kShapeCoordScalar); - uniforms.SetMatrix4x4Value("modelView", mv.m_data); - glsl::vec4 const color = glsl::ToVec4(df::GetColorConstant(m_routeData->m_color)); - uniforms.SetFloatValue("u_color", color.r, color.g, color.b, color.a); - double const screenScale = screen.GetScale(); - uniforms.SetFloatValue("u_routeParams", m_currentHalfWidth, m_currentHalfWidth * screenScale, - m_distanceFromBegin, trafficShown ? 1.0f : 0.0f); - - if (m_routeData->m_pattern.m_isDashed) - { - uniforms.SetFloatValue("u_pattern", m_currentHalfWidth * m_routeData->m_pattern.m_dashLength * screenScale, - m_currentHalfWidth * m_routeData->m_pattern.m_gapLength * screenScale); - } - else - { - glsl::vec4 const outlineColor = glsl::ToVec4(GetOutlineColor(m_routeData->m_color)); - uniforms.SetFloatValue("u_outlineColor", outlineColor.r, outlineColor.g, outlineColor.b, outlineColor.a); - } - - // Set up shaders and apply uniforms. - ref_ptr prg = mng->GetProgram(m_routeData->m_pattern.m_isDashed ? - gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM); - prg->Bind(); - dp::ApplyState(state, prg); - dp::ApplyUniforms(uniforms, prg); - - // Render buckets. - for (drape_ptr const & bucket : m_routeData->m_route.m_buckets) - bucket->Render(state.GetDrawAsLine()); - } + for (auto const & routeData : m_routeData) + RenderRouteData(routeData, screen, trafficShown, mng, commonUniforms); // Render arrows. - if (m_routeArrows != nullptr) - { - dp::GLState const & state = m_routeArrows->m_arrows.m_state; - - // set up shaders and apply common uniforms - dp::UniformValuesStorage uniforms = commonUniforms; - math::Matrix mv = screen.GetModelView(m_routeArrows->m_pivot, kShapeCoordScalar); - uniforms.SetMatrix4x4Value("modelView", mv.m_data); - uniforms.SetFloatValue("u_arrowHalfWidth", m_currentHalfWidth * kArrowHeightFactor); - uniforms.SetFloatValue("u_opacity", 1.0f); - - ref_ptr prg = mng->GetProgram(gpu::ROUTE_ARROW_PROGRAM); - prg->Bind(); - dp::ApplyState(state, prg); - dp::ApplyUniforms(uniforms, prg); - for (drape_ptr const & bucket : m_routeArrows->m_arrows.m_buckets) - bucket->Render(state.GetDrawAsLine()); - } + for (auto const & p : m_routeAdditional) + RenderRouteArrowData(p.first, p.second, screen, mng, commonUniforms); } -void RouteRenderer::RenderRouteSigns(ScreenBase const & screen, ref_ptr mng, - dp::UniformValuesStorage const & commonUniforms) +void RouteRenderer::AddRouteData(drape_ptr && routeData, + ref_ptr mng) { - if (m_startRouteSign) - { - ASSERT(m_startRouteSign->m_isValid, ()); - RenderRouteSign(m_startRouteSign, screen, mng, commonUniforms); - } + // Remove old route data with the same id. + RemoveRouteData(routeData->m_segmentId); - if (m_finishRouteSign) - { - ASSERT(m_finishRouteSign->m_isValid, ()); - RenderRouteSign(m_finishRouteSign, screen, mng, commonUniforms); - } + // Add new route data. + m_routeData.push_back(std::move(routeData)); + BuildBuckets(m_routeData.back()->m_renderProperty, mng); } -void RouteRenderer::RenderRouteSign(drape_ptr const & sign, ScreenBase const & screen, - ref_ptr mng, - dp::UniformValuesStorage const & commonUniforms) -{ - if (sign->m_sign.m_buckets.empty()) - return; - - dp::GLState const & state = sign->m_sign.m_state; - dp::UniformValuesStorage uniforms = commonUniforms; - math::Matrix mv = screen.GetModelView(sign->m_position, 1.0); - uniforms.SetMatrix4x4Value("modelView", mv.m_data); - uniforms.SetFloatValue("u_opacity", 1.0f); - - ref_ptr program = screen.isPerspective() ? mng->GetProgram(state.GetProgram3dIndex()) - : mng->GetProgram(state.GetProgramIndex()); - program->Bind(); - - dp::ApplyState(state, program); - dp::ApplyUniforms(uniforms, program); - - for (auto const & bucket : sign->m_sign.m_buckets) - { - bucket->GetBuffer()->Build(program); - bucket->Render(state.GetDrawAsLine()); - } -} - -void RouteRenderer::SetRouteData(drape_ptr && routeData, ref_ptr mng) -{ - m_routeData = move(routeData); - m_arrowBorders.clear(); - - BuildBuckets(m_routeData->m_route, mng); -} - -void RouteRenderer::SetRouteSign(drape_ptr && routeSignData, ref_ptr mng) -{ - if (routeSignData->m_isStart) - { - if (!routeSignData->m_isValid) - { - m_startRouteSign.reset(); - return; - } - - m_startRouteSign = move(routeSignData); - BuildBuckets(m_startRouteSign->m_sign, mng); - } - else - { - if (!routeSignData->m_isValid) - { - m_finishRouteSign.reset(); - return; - } - - m_finishRouteSign = move(routeSignData); - BuildBuckets(m_finishRouteSign->m_sign, mng); - } -} - -drape_ptr const & RouteRenderer::GetStartPoint() const -{ - return m_startRouteSign; -} - -drape_ptr const & RouteRenderer::GetFinishPoint() const -{ - return m_finishRouteSign; -} - -drape_ptr const & RouteRenderer::GetRouteData() const +std::vector> const & RouteRenderer::GetRouteData() const { return m_routeData; } -void RouteRenderer::SetRouteArrows(drape_ptr && routeArrowsData, - ref_ptr mng) +void RouteRenderer::RemoveRouteData(dp::DrapeID segmentId) { - m_routeArrows = move(routeArrowsData); - BuildBuckets(m_routeArrows->m_arrows, mng); + auto const functor = [&segmentId](drape_ptr const & data) + { + return data->m_segmentId == segmentId; + }; + m_routeData.erase(std::remove_if(m_routeData.begin(), m_routeData.end(), functor), + m_routeData.end()); + m_routeAdditional[segmentId].m_arrowsData.reset(); + m_routeAdditional[segmentId].m_arrowBorders.clear(); +} + +void RouteRenderer::AddRouteArrowsData(drape_ptr && routeArrowsData, + ref_ptr mng) +{ + auto & additional = m_routeAdditional[routeArrowsData->m_segmentId]; + additional.m_arrowsData = std::move(routeArrowsData); + BuildBuckets(additional.m_arrowsData->m_renderProperty, mng); +} + +void RouteRenderer::ClearRouteData() +{ + m_routeData.clear(); + m_routeAdditional.clear(); } void RouteRenderer::Clear() { - m_routeData.reset(); - m_startRouteSign.reset(); - m_finishRouteSign.reset(); - m_arrowBorders.clear(); - m_routeArrows.reset(); + ClearRouteData(); m_distanceFromBegin = 0.0; } void RouteRenderer::ClearGLDependentResources() { - if (m_routeData != nullptr) - m_routeData->m_route = RouteRenderProperty(); - if (m_startRouteSign != nullptr) - m_startRouteSign->m_sign = RouteRenderProperty(); - if (m_finishRouteSign != nullptr) - m_finishRouteSign->m_sign = RouteRenderProperty(); - m_routeArrows.reset(); + // Here we clear only GL-dependent part of route data. + for (auto & routeData : m_routeData) + routeData->m_renderProperty = RouteRenderProperty(); + + // All additional data (like arrows) will be regenerated, so clear them all. + m_routeAdditional.clear(); } void RouteRenderer::UpdateDistanceFromBegin(double distanceFromBegin) @@ -426,4 +417,8 @@ void RouteRenderer::UpdateDistanceFromBegin(double distanceFromBegin) m_distanceFromBegin = distanceFromBegin; } -} // namespace df +void RouteRenderer::SetFollowingEnabled(bool enabled) +{ + m_followingEnabled = enabled; +} +} // namespace df diff --git a/drape_frontend/route_renderer.hpp b/drape_frontend/route_renderer.hpp index 025b76f66a..2a0ff6167f 100644 --- a/drape_frontend/route_renderer.hpp +++ b/drape_frontend/route_renderer.hpp @@ -2,16 +2,19 @@ #include "drape_frontend/route_builder.hpp" +#include "drape/drape_global.hpp" #include "drape/gpu_program_manager.hpp" #include "drape/pointers.hpp" #include "geometry/screenbase.hpp" +#include #include +#include +#include namespace df { - extern std::string const kRouteColor; extern std::string const kRouteOutlineColor; extern std::string const kRoutePedestrian; @@ -20,49 +23,50 @@ extern std::string const kRouteBicycle; class RouteRenderer final { public: - using TCacheRouteArrowsCallback = function const &)>; + using TCacheRouteArrowsCallback = std::function const &)>; RouteRenderer(); void UpdateRoute(ScreenBase const & screen, TCacheRouteArrowsCallback const & callback); - void RenderRoute(ScreenBase const & screen, bool trafficShown, - ref_ptr mng, + void RenderRoute(ScreenBase const & screen, bool trafficShown, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms); - void RenderRouteSigns(ScreenBase const & screen, ref_ptr mng, - dp::UniformValuesStorage const & commonUniforms); + void AddRouteData(drape_ptr && routeData, ref_ptr mng); + std::vector> const & GetRouteData() const; - void SetRouteData(drape_ptr && routeData, ref_ptr mng); - drape_ptr const & GetRouteData() const; + void RemoveRouteData(dp::DrapeID segmentId); - void SetRouteSign(drape_ptr && routeSignData, ref_ptr mng); - drape_ptr const & GetStartPoint() const; - drape_ptr const & GetFinishPoint() const; - - void SetRouteArrows(drape_ptr && routeArrowsData, ref_ptr mng); + void AddRouteArrowsData(drape_ptr && routeArrowsData, + ref_ptr mng); void Clear(); + void ClearRouteData(); void ClearGLDependentResources(); void UpdateDistanceFromBegin(double distanceFromBegin); + void SetFollowingEnabled(bool enabled); private: - void InterpolateByZoom(ScreenBase const & screen, ColorConstant color, + struct RouteAdditional + { + drape_ptr m_arrowsData; + std::vector m_arrowBorders; + float m_currentHalfWidth = 0.0f; + }; + + void InterpolateByZoom(drape_ptr const & routeSegment, ScreenBase const & screen, float & halfWidth, double & zoom) const; - void RenderRouteSign(drape_ptr const & sign, ScreenBase const & screen, - ref_ptr mng, dp::UniformValuesStorage const & commonUniforms); + void RenderRouteData(drape_ptr const & routeData, ScreenBase const & screen, + bool trafficShown, ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms); + void RenderRouteArrowData(dp::DrapeID segmentId, RouteAdditional const & routeAdditional, + ScreenBase const & screen, ref_ptr mng, + dp::UniformValuesStorage const & commonUniforms); double m_distanceFromBegin; - drape_ptr m_routeData; - - vector m_arrowBorders; - drape_ptr m_routeArrows; - - drape_ptr m_startRouteSign; - drape_ptr m_finishRouteSign; - - float m_currentHalfWidth = 0.0f; + std::vector> m_routeData; + std::unordered_map m_routeAdditional; + bool m_followingEnabled; }; - -} // namespace df +} // namespace df diff --git a/drape_frontend/route_shape.cpp b/drape_frontend/route_shape.cpp index 9c78fba1eb..52a2bc7d8e 100644 --- a/drape_frontend/route_shape.cpp +++ b/drape_frontend/route_shape.cpp @@ -24,12 +24,14 @@ float const kRightSide = -1.0f; float const kRouteDepth = 100.0f; float const kArrowsDepth = 200.0f; -void GetArrowTextureRegion(ref_ptr textures, dp::TextureManager::SymbolRegion & region) +void GetArrowTextureRegion(ref_ptr textures, + dp::TextureManager::SymbolRegion & region) { textures->GetSymbolRegion("route-arrow", region); } -std::vector CalculatePoints(m2::PolylineD const & polyline, double start, double end) +std::vector CalculatePoints(m2::PolylineD const & polyline, + double start, double end) { std::vector result; result.reserve(polyline.GetSize() / 4); @@ -77,18 +79,23 @@ std::vector CalculatePoints(m2::PolylineD const & polyline, double s return result; } +float SideByNormal(glsl::vec2 const & normal, bool isLeft) +{ + float const kEps = 1e-5; + float const side = isLeft ? kLeftSide : kRightSide; + return glsl::length(normal) < kEps ? kCenter : side; +} + void GenerateJoinsTriangles(glsl::vec3 const & pivot, std::vector const & normals, glsl::vec4 const & color, glsl::vec2 const & length, bool isLeft, RouteShape::TGeometryBuffer & joinsGeometry) { - float const kEps = 1e-5; size_t const trianglesCount = normals.size() / 3; - float const side = isLeft ? kLeftSide : kRightSide; for (size_t j = 0; j < trianglesCount; j++) { - glsl::vec3 const len1 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j]) < kEps ? kCenter : side); - glsl::vec3 const len2 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j + 1]) < kEps ? kCenter : side); - glsl::vec3 const len3 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j + 2]) < kEps ? kCenter : side); + glsl::vec3 const len1 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j], isLeft)); + glsl::vec3 const len2 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j + 1], isLeft)); + glsl::vec3 const len3 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j + 2], isLeft)); joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j], len1, color)); joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j + 1], len2, color)); @@ -175,15 +182,23 @@ void RouteShape::PrepareGeometry(std::vector const & path, m2::Point float const projRightStart = -segments[i].m_rightWidthScalar[StartPoint].y; float const projRightEnd = segments[i].m_rightWidthScalar[EndPoint].y; - geometry.push_back(RV(startPivot, glsl::vec2(0, 0), glsl::vec3(startLength, 0, kCenter), segments[i].m_color)); - geometry.push_back(RV(startPivot, leftNormalStart, glsl::vec3(startLength, projLeftStart, kLeftSide), segments[i].m_color)); - geometry.push_back(RV(endPivot, glsl::vec2(0, 0), glsl::vec3(length, 0, kCenter), segments[i].m_color)); - geometry.push_back(RV(endPivot, leftNormalEnd, glsl::vec3(length, projLeftEnd, kLeftSide), segments[i].m_color)); + geometry.push_back(RV(startPivot, glsl::vec2(0, 0), + glsl::vec3(startLength, 0, kCenter), segments[i].m_color)); + geometry.push_back(RV(startPivot, leftNormalStart, + glsl::vec3(startLength, projLeftStart, kLeftSide), segments[i].m_color)); + geometry.push_back(RV(endPivot, glsl::vec2(0, 0), + glsl::vec3(length, 0, kCenter), segments[i].m_color)); + geometry.push_back(RV(endPivot, leftNormalEnd, + glsl::vec3(length, projLeftEnd, kLeftSide), segments[i].m_color)); - geometry.push_back(RV(startPivot, rightNormalStart, glsl::vec3(startLength, projRightStart, kRightSide), segments[i].m_color)); - geometry.push_back(RV(startPivot, glsl::vec2(0, 0), glsl::vec3(startLength, 0, kCenter), segments[i].m_color)); - geometry.push_back(RV(endPivot, rightNormalEnd, glsl::vec3(length, projRightEnd, kRightSide), segments[i].m_color)); - geometry.push_back(RV(endPivot, glsl::vec2(0, 0), glsl::vec3(length, 0, kCenter), segments[i].m_color)); + geometry.push_back(RV(startPivot, rightNormalStart, + glsl::vec3(startLength, projRightStart, kRightSide), segments[i].m_color)); + geometry.push_back(RV(startPivot, glsl::vec2(0, 0), + glsl::vec3(startLength, 0, kCenter), segments[i].m_color)); + geometry.push_back(RV(endPivot, rightNormalEnd, + glsl::vec3(length, projRightEnd, kRightSide), segments[i].m_color)); + geometry.push_back(RV(endPivot, glsl::vec2(0, 0), + glsl::vec3(length, 0, kCenter), segments[i].m_color)); // Generate joins. if (segments[i].m_generateJoin && i < static_cast(segments.size()) - 1) @@ -352,45 +367,6 @@ void RouteShape::PrepareArrowGeometry(std::vector const & path, m2:: } } -void RouteShape::CacheRouteSign(ref_ptr mng, RouteSignData & routeSignData) -{ - dp::TextureManager::SymbolRegion symbol; - mng->GetSymbolRegion(routeSignData.m_isStart ? "route_from" : "route_to", symbol); - - m2::RectF const & texRect = symbol.GetTexRect(); - m2::PointF halfSize = symbol.GetPixelSize() * 0.5f; - - glsl::vec4 const pivot = glsl::vec4(0.0f /* x */, 0.0f /* y */, 0.0f /* depth */, 0.0f /* pivot z */); - gpu::SolidTexturingVertex data[4]= - { - { pivot, glsl::vec2(-halfSize.x, halfSize.y), glsl::ToVec2(texRect.LeftTop()) }, - { pivot, glsl::vec2(-halfSize.x, -halfSize.y), glsl::ToVec2(texRect.LeftBottom()) }, - { pivot, glsl::vec2( halfSize.x, halfSize.y), glsl::ToVec2(texRect.RightTop()) }, - { pivot, glsl::vec2( halfSize.x, -halfSize.y), glsl::ToVec2(texRect.RightBottom()) } - }; - - dp::GLState state(gpu::TEXTURING_PROGRAM, dp::GLState::OverlayLayer); - if (!routeSignData.m_isStart) - state.SetProgram3dIndex(gpu::TEXTURING_BILLBOARD_PROGRAM); - state.SetColorTexture(symbol.GetTexture()); - - { - dp::Batcher batcher(dp::Batcher::IndexPerQuad, dp::Batcher::VertexPerQuad); - dp::SessionGuard guard(batcher, [&routeSignData](dp::GLState const & state, drape_ptr && b) - { - routeSignData.m_sign.m_buckets.push_back(move(b)); - routeSignData.m_sign.m_state = state; - }); - - dp::AttributeProvider provider(1 /* stream count */, dp::Batcher::VertexPerQuad); - provider.InitStream(0 /* stream index */, gpu::SolidTexturingVertex::GetBindingInfo(), make_ref(data)); - - dp::IndicesRange indices = batcher.InsertTriangleStrip(state, make_ref(&provider), nullptr); - UNUSED_VALUE(indices); - ASSERT(indices.IsValid(), ()); - } -} - void RouteShape::CacheRouteArrows(ref_ptr mng, m2::PolylineD const & polyline, std::vector const & borders, RouteArrowsData & routeArrowsData) @@ -416,14 +392,14 @@ void RouteShape::CacheRouteArrows(ref_ptr mng, m2::PolylineD BatchGeometry(state, make_ref(geometry.data()), static_cast(geometry.size()), make_ref(joinsGeometry.data()), static_cast(joinsGeometry.size()), - AV::GetBindingInfo(), routeArrowsData.m_arrows); + AV::GetBindingInfo(), routeArrowsData.m_renderProperty); } void RouteShape::CacheRoute(ref_ptr textures, RouteData & routeData) { std::vector segmentsColors; - segmentsColors.reserve(routeData.m_traffic.size()); - for (auto speedGroup : routeData.m_traffic) + segmentsColors.reserve(routeData.m_segment->m_traffic.size()); + for (auto speedGroup : routeData.m_segment->m_traffic) { speedGroup = TrafficGenerator::CheckColorsSimplification(speedGroup); auto const colorConstant = TrafficGenerator::GetColorBySpeedGroup(speedGroup, true /* route */); @@ -436,16 +412,17 @@ void RouteShape::CacheRoute(ref_ptr textures, RouteData & ro TGeometryBuffer geometry; TGeometryBuffer joinsGeometry; - PrepareGeometry(routeData.m_sourcePolyline.GetPoints(), routeData.m_pivot, segmentsColors, + PrepareGeometry(routeData.m_segment->m_polyline.GetPoints(), routeData.m_pivot, segmentsColors, geometry, joinsGeometry, routeData.m_length); - dp::GLState state = - dp::GLState(routeData.m_pattern.m_isDashed ? gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM, - dp::GLState::GeometryLayer); + dp::GLState state = dp::GLState(routeData.m_segment->m_pattern.m_isDashed ? + gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM, + dp::GLState::GeometryLayer); state.SetColorTexture(textures->GetSymbolsTexture()); + BatchGeometry(state, make_ref(geometry.data()), static_cast(geometry.size()), make_ref(joinsGeometry.data()), static_cast(joinsGeometry.size()), - RV::GetBindingInfo(), routeData.m_route); + RV::GetBindingInfo(), routeData.m_renderProperty); } void RouteShape::BatchGeometry(dp::GLState const & state, ref_ptr geometry, uint32_t geomSize, @@ -453,29 +430,29 @@ void RouteShape::BatchGeometry(dp::GLState const & state, ref_ptr geometry dp::BindingInfo const & bindingInfo, RouteRenderProperty & property) { size_t const verticesCount = geomSize + joinsGeomSize; - if (verticesCount != 0) + if (verticesCount == 0) + return; + + uint32_t const kBatchSize = 5000; + dp::Batcher batcher(kBatchSize, kBatchSize); + dp::SessionGuard guard(batcher, [&property](dp::GLState const & state, drape_ptr && b) { - uint32_t const kBatchSize = 5000; - dp::Batcher batcher(kBatchSize, kBatchSize); - dp::SessionGuard guard(batcher, [&property](dp::GLState const & state, drape_ptr && b) - { - property.m_buckets.push_back(move(b)); - property.m_state = state; - }); + property.m_buckets.push_back(move(b)); + property.m_state = state; + }); - if (geomSize != 0) - { - dp::AttributeProvider provider(1 /* stream count */, geomSize); - provider.InitStream(0 /* stream index */, bindingInfo, geometry); - batcher.InsertListOfStrip(state, make_ref(&provider), 4); - } + if (geomSize != 0) + { + dp::AttributeProvider provider(1 /* stream count */, geomSize); + provider.InitStream(0 /* stream index */, bindingInfo, geometry); + batcher.InsertListOfStrip(state, make_ref(&provider), 4); + } - if (joinsGeomSize != 0) - { - dp::AttributeProvider joinsProvider(1 /* stream count */, joinsGeomSize); - joinsProvider.InitStream(0 /* stream index */, bindingInfo, joinsGeometry); - batcher.InsertTriangleList(state, make_ref(&joinsProvider)); - } + if (joinsGeomSize != 0) + { + dp::AttributeProvider joinsProvider(1 /* stream count */, joinsGeomSize); + joinsProvider.InitStream(0 /* stream index */, bindingInfo, joinsGeometry); + batcher.InsertTriangleList(state, make_ref(&joinsProvider)); } } } // namespace df diff --git a/drape_frontend/route_shape.hpp b/drape_frontend/route_shape.hpp index bab193800d..8d2acf7bf5 100644 --- a/drape_frontend/route_shape.hpp +++ b/drape_frontend/route_shape.hpp @@ -33,6 +33,14 @@ float const kArrowTailFactor = static_cast(2.0 * kArrowTailTextureWidth / double const kArrowHeightFactor = kArrowTextureHeight / kArrowBodyHeight; double const kArrowAspect = kArrowTextureWidth / kArrowTextureHeight; +enum class RouteType : uint8_t +{ + Car, + Pedestrian, + Bicycle, + Taxi +}; + struct RoutePattern { bool m_isDashed = false; @@ -48,6 +56,24 @@ struct RoutePattern {} }; +struct RouteSegment +{ + df::RouteType m_routeType; + m2::PolylineD m_polyline; + df::ColorConstant m_color; + std::vector m_turns; + std::vector m_traffic; + df::RoutePattern m_pattern; + + RouteSegment() = default; + RouteSegment(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) + {} +}; + struct RouteRenderProperty { dp::GLState m_state; @@ -55,43 +81,29 @@ struct RouteRenderProperty RouteRenderProperty() : m_state(0, dp::GLState::GeometryLayer) {} }; +struct BaseRouteData +{ + dp::DrapeID m_segmentId = 0; + m2::PointD m_pivot = m2::PointD(0.0, 0.0); + int m_recacheId = -1; + RouteRenderProperty m_renderProperty; +}; + +struct RouteData : public BaseRouteData +{ + drape_ptr m_segment; + double m_length = 0.0; +}; + +struct RouteArrowsData : public BaseRouteData {}; + struct ArrowBorders { - double m_startDistance = 0; - double m_endDistance = 0; + double m_startDistance = 0.0; + double m_endDistance = 0.0; int m_groupIndex = 0; }; -struct RouteData -{ - int m_routeIndex; - m2::PolylineD m_sourcePolyline; - std::vector m_sourceTurns; - m2::PointD m_pivot; - df::ColorConstant m_color; - std::vector m_traffic; - double m_length; - RouteRenderProperty m_route; - RoutePattern m_pattern; - int m_recacheId; -}; - -struct RouteSignData -{ - RouteRenderProperty m_sign; - bool m_isStart; - bool m_isValid; - m2::PointD m_position; - int m_recacheId; -}; - -struct RouteArrowsData -{ - RouteRenderProperty m_arrows; - m2::PointD m_pivot; - int m_recacheId; -}; - class RouteShape { public: @@ -101,7 +113,7 @@ public: using TArrowGeometryBuffer = buffer_vector; static void CacheRoute(ref_ptr textures, RouteData & routeData); - static void CacheRouteSign(ref_ptr mng, RouteSignData & routeSignData); + static void CacheRouteArrows(ref_ptr mng, m2::PolylineD const & polyline, std::vector const & borders, RouteArrowsData & routeArrowsData); diff --git a/iphone/Maps/Core/Routing/MWMRouter.mm b/iphone/Maps/Core/Routing/MWMRouter.mm index d7abb0aa47..b459171276 100644 --- a/iphone/Maps/Core/Routing/MWMRouter.mm +++ b/iphone/Maps/Core/Routing/MWMRouter.mm @@ -202,8 +202,8 @@ bool isMarkerPoint(MWMRoutePoint * point) { return point.isValid && !point.isMyP self.type = routerType(GetFramework().GetRoutingManager().GetBestRouter(startPoint, finishPoint)); f.GetRoutingManager().BuildRoute(startPoint, finishPoint, isP2P, 0 /* timeoutSec */); - f.GetRoutingManager().SetRouteStartPoint(startPoint, isMarkerPoint(self.startPoint)); - f.GetRoutingManager().SetRouteFinishPoint(finishPoint, isMarkerPoint(self.finishPoint)); + f.GetRoutingManager().SetRouteStartPoint(f.GetBookmarkManager(), startPoint, isMarkerPoint(self.startPoint)); + f.GetRoutingManager().SetRouteFinishPoint(f.GetBookmarkManager(), finishPoint, isMarkerPoint(self.finishPoint)); [mapViewControlsManager onRouteRebuild]; } diff --git a/map/place_page_info.cpp b/map/place_page_info.cpp index 4eb6ec48c1..b756123a75 100644 --- a/map/place_page_info.cpp +++ b/map/place_page_info.cpp @@ -28,6 +28,12 @@ bool Info::IsNotEditableSponsored() const return m_sponsoredType != SponsoredType::None && m_sponsoredType != SponsoredType::Opentable; } +bool Info::IsRoutePoint() const +{ + //TODO(@darina) Implement checker + return m_bac.IsValid() && m_bookmarkCategoryName == "TMP_Routing_Points"; +} + bool Info::ShouldShowAddPlace() const { auto const isPointOrBuilding = IsPointType() || IsBuilding(); diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp index 40f9d87dec..ddc54c5994 100644 --- a/map/place_page_info.hpp +++ b/map/place_page_info.hpp @@ -53,6 +53,7 @@ public: bool IsMyPosition() const; bool IsSponsored() const; bool IsNotEditableSponsored() const; + bool IsRoutePoint() const; bool ShouldShowAddPlace() const; bool ShouldShowAddBusiness() const; diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 3ce9ad5e9b..6ae6c26102 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -184,8 +184,9 @@ void RoutingManager::SetRouterImpl(routing::RouterType type) void RoutingManager::RemoveRoute(bool deactivateFollowing) { + // TODO(@rokuz) use correct DrapeID if (m_drapeEngine != nullptr) - m_drapeEngine->RemoveRoute(deactivateFollowing); + m_drapeEngine->RemoveRouteSegment(dp::DrapeID(), deactivateFollowing); } void RoutingManager::InsertRoute(routing::Route const & route) @@ -199,27 +200,38 @@ void RoutingManager::InsertRoute(routing::Route const & route) return; } - std::vector turns; - if (m_currentRouterType == RouterType::Vehicle || m_currentRouterType == RouterType::Bicycle || - m_currentRouterType == RouterType::Taxi) + auto segment = make_unique_dp(); + segment->m_polyline = route.GetPoly(); + switch (m_currentRouterType) { - route.GetTurnsDistances(turns); + case RouterType::Vehicle: + segment->m_routeType = df::RouteType::Car; + segment->m_color = df::kRouteColor; + segment->m_traffic = route.GetTraffic(); + route.GetTurnsDistances(segment->m_turns); + break; + case RouterType::Pedestrian: + segment->m_routeType = df::RouteType::Pedestrian; + segment->m_color = df::kRoutePedestrian; + segment->m_pattern = df::RoutePattern(4.0, 2.0); + break; + case RouterType::Bicycle: + segment->m_routeType = df::RouteType::Bicycle; + segment->m_color = df::kRouteBicycle; + segment->m_pattern = df::RoutePattern(8.0, 2.0); + route.GetTurnsDistances(segment->m_turns); + break; + case RouterType::Taxi: + segment->m_routeType = df::RouteType::Taxi; + segment->m_color = df::kRouteColor; + segment->m_traffic = route.GetTraffic(); + route.GetTurnsDistances(segment->m_turns); + break; + default: ASSERT(false, ("Unknown router type")); } - df::ColorConstant routeColor = df::kRouteColor; - df::RoutePattern pattern; - if (m_currentRouterType == RouterType::Pedestrian) - { - routeColor = df::kRoutePedestrian; - pattern = df::RoutePattern(4.0, 2.0); - } - else if (m_currentRouterType == RouterType::Bicycle) - { - routeColor = df::kRouteBicycle; - pattern = df::RoutePattern(8.0, 2.0); - } - - m_drapeEngine->AddRoute(route.GetPoly(), turns, routeColor, route.GetTraffic(), pattern); + dp::DrapeID const segmentId = m_drapeEngine->AddRouteSegment(std::move(segment)); + // TODO (@rokuz) Save and use segment id } void RoutingManager::FollowRoute() @@ -230,7 +242,8 @@ void RoutingManager::FollowRoute() return; m_delegate.OnRouteFollow(m_currentRouterType); - m_drapeEngine->SetRoutePoint(m2::PointD(), true /* isStart */, false /* isValid */); + + // TODO(@darina) Hide start point user mark } void RoutingManager::CloseRouting() @@ -241,6 +254,8 @@ void RoutingManager::CloseRouting() } m_routingSession.Reset(); RemoveRoute(true /* deactivateFollowing */); + + //TODO (@darina) Remove route points } void RoutingManager::SetLastUsedRouter(RouterType type) @@ -248,16 +263,71 @@ void RoutingManager::SetLastUsedRouter(RouterType type) settings::Set(kRouterTypeKey, routing::ToString(type)); } -void RoutingManager::SetRouteStartPoint(m2::PointD const & pt, bool isValid) +// TODO(@darina) Remove me +// TEMPORARY { +void TempAddBookmarkAsRoutePoint(BookmarkManager & bm, std::string const & name, + std::string const & bookmarkSymbol, + m2::PointD const & pt, bool isValid) { - if (m_drapeEngine != nullptr) - m_drapeEngine->SetRoutePoint(pt, true /* isStart */, isValid); + std::string categoryName = "TMP_Routing_Points"; + int categoryIndex = -1; + for (size_t i = 0; i < bm.GetBmCategoriesCount(); ++i) + { + if (bm.GetBmCategory(i)->GetName() == categoryName) + { + categoryIndex = static_cast(i); + break; + } + } + if (categoryIndex == -1) + categoryIndex = bm.CreateBmCategory(categoryName); + + if (!isValid) + { + BookmarkCategory * cat = bm.GetBmCategory(categoryIndex); + BookmarkCategory::Guard guard(*cat); + int indexToDelete = -1; + for (size_t i = 0; i < guard.m_controller.GetUserMarkCount(); ++i) + { + Bookmark const * bookmark = static_cast(guard.m_controller.GetUserMark(i)); + if (bookmark->GetName() == name) + { + indexToDelete = i; + break; + } + } + if (indexToDelete >= 0) + guard.m_controller.DeleteUserMark(indexToDelete); + } + else + { + BookmarkData dat(name, bookmarkSymbol); + bm.AddBookmark(categoryIndex, pt, dat); + } + + { + BookmarkCategory * cat = bm.GetBmCategory(categoryIndex); + cat->SaveToKMLFile(); + } +} +// } TEMPORARY + +void RoutingManager::SetRouteStartPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid) +{ + // TODO(@darina) Implement on new user marks + // TEMPORARY { + //TempAddBookmarkAsRoutePoint(bm, "Route start point", "placemark-blue", + // pt, isValid); + // } TEMPORARY } -void RoutingManager::SetRouteFinishPoint(m2::PointD const & pt, bool isValid) +void RoutingManager::SetRouteFinishPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid) { - if (m_drapeEngine != nullptr) - m_drapeEngine->SetRoutePoint(pt, false /* isStart */, isValid); + // TODO(@darina) Implement on new user marks + // TEMPORARY { + //TempAddBookmarkAsRoutePoint(bm, "Route end point", "placemark-green", + // pt, isValid); + // } TEMPORARY } void RoutingManager::GenerateTurnNotifications(std::vector & turnNotifications) diff --git a/map/routing_manager.hpp b/map/routing_manager.hpp index 35e43a36fc..de9c76669d 100644 --- a/map/routing_manager.hpp +++ b/map/routing_manager.hpp @@ -1,10 +1,15 @@ -#include "drape/pointers.hpp" +#pragma once + +// TODO (@darina) TEMPORARY Remove me +#include "map/bookmark_manager.hpp" #include "routing/route.hpp" #include "routing/routing_session.hpp" #include "storage/index.hpp" +#include "drape/pointers.hpp" + #include "tracking/reporter.hpp" #include "base/thread_checker.hpp" @@ -154,8 +159,9 @@ public: /// GenerateTurnNotifications shall be called by the client when a new position is available. void GenerateTurnNotifications(std::vector & turnNotifications); - void SetRouteStartPoint(m2::PointD const & pt, bool isValid); - void SetRouteFinishPoint(m2::PointD const & pt, bool isValid); + // TODO (@darina) Change interface to add/remove route point + void SetRouteStartPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid); + void SetRouteFinishPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid); void SetRouterImpl(routing::RouterType type); void RemoveRoute(bool deactivateFollowing); @@ -171,7 +177,10 @@ public: m_trackingReporter.SetAllowSendingPoints(isAllowed); } - void SetTurnNotificationsUnits(measurement_utils::Units const units) { m_routingSession.SetTurnNotificationsUnits(units); } + void SetTurnNotificationsUnits(measurement_utils::Units const units) + { + m_routingSession.SetTurnNotificationsUnits(units); + } void SetDrapeEngine(ref_ptr engine, bool is3dAllowed); /// \returns true if altitude information along |m_route| is available and /// false otherwise. @@ -199,13 +208,13 @@ private: void MatchLocationToRoute(location::GpsInfo & info, location::RouteMatchingInfo & routeMatchingInfo) const; -private: RouteBuildingCallback m_routingCallback = nullptr; Callbacks m_callbacks; ref_ptr m_drapeEngine = nullptr; routing::RouterType m_currentRouterType = routing::RouterType::Count; routing::RoutingSession m_routingSession; - DECLARE_THREAD_CHECKER(m_threadChecker); Delegate & m_delegate; tracking::Reporter m_trackingReporter; + + DECLARE_THREAD_CHECKER(m_threadChecker); };