From 46530363dbf70c6460562cdf33168e15f2646341 Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Wed, 9 Aug 2017 16:52:18 +0300 Subject: [PATCH] User lines indexing is limited to several zoom levels. --- drape_frontend/user_mark_generator.cpp | 133 ++++++++++++++++--------- drape_frontend/user_mark_generator.hpp | 10 ++ drape_frontend/user_mark_shapes.cpp | 60 ++++++++++- drape_frontend/user_mark_shapes.hpp | 3 + 4 files changed, 158 insertions(+), 48 deletions(-) diff --git a/drape_frontend/user_mark_generator.cpp b/drape_frontend/user_mark_generator.cpp index be7438ae53..510962c679 100644 --- a/drape_frontend/user_mark_generator.cpp +++ b/drape_frontend/user_mark_generator.cpp @@ -12,6 +12,9 @@ namespace df { + +std::vector const kLineIndexingLevels = {1, 7, 11}; + UserMarkGenerator::UserMarkGenerator(TFlushFn const & flushFn) : m_flushFn(flushFn) { @@ -107,42 +110,26 @@ void UserMarkGenerator::UpdateIndex(MarkGroupID groupId) { UserLineRenderParams const & params = *m_lines[lineId].get(); - double const splineFullLength = params.m_spline->GetLength(); - - for (int zoomLevel = params.m_minZoom; zoomLevel <= scales::GetUpperScale(); ++zoomLevel) + int const startZoom = GetNearestLineIndexZoom(params.m_minZoom); + for (int zoomLevel : kLineIndexingLevels) { - double length = 0; - while (length < splineFullLength) + if (zoomLevel < startZoom) + continue; + // Process spline by segments that no longer than tile size. + double const range = MercatorBounds::maxX - MercatorBounds::minX; + double const maxLength = range / (1 << (zoomLevel - 1)); + + df::ProcessSplineSegmentRects(params.m_spline, maxLength, + [&](m2::RectD const & segmentRect) -> bool { - // Process spline by segments that no longer than tile size. - double const range = MercatorBounds::maxX - MercatorBounds::minX; - double const maxLength = range / (1 << (zoomLevel - 1)); - - m2::RectD splineRect; - - auto const itBegin = params.m_spline->GetPoint(length); - auto itEnd = params.m_spline->GetPoint(length + maxLength); - if (itEnd.BeginAgain()) - { - double const lastSegmentLength = params.m_spline->GetLengths().back(); - itEnd = params.m_spline->GetPoint(splineFullLength - lastSegmentLength / 2.0); - splineRect.Add(params.m_spline->GetPath().back()); - } - - params.m_spline->ForEachNode(itBegin, itEnd, [&splineRect](m2::PointD const & pt) - { - splineRect.Add(pt); - }); - - length += maxLength; - - CalcTilesCoverage(splineRect, zoomLevel, [&](int tileX, int tileY) + CalcTilesCoverage(segmentRect, zoomLevel, [&](int tileX, int tileY) { TileKey const tileKey(tileX, tileY, zoomLevel); ref_ptr groupIDs = GetIdCollection(tileKey, groupId); groupIDs->m_linesID.push_back(static_cast(lineId)); }); - } + return true; + }); } } @@ -210,35 +197,91 @@ void UserMarkGenerator::SetGroupVisibility(MarkGroupID groupId, bool isVisible) m_groupsVisibility.erase(groupId); } +ref_ptr UserMarkGenerator::GetUserMarksGroups(TileKey const & tileKey) +{ + auto const itTile = m_index.find(tileKey); + if (itTile != m_index.end()) + return make_ref(itTile->second); + return nullptr; +} + +ref_ptr UserMarkGenerator::GetUserLinesGroups(TileKey const & tileKey) +{ + auto itTile = m_index.end(); + int const lineZoom = GetNearestLineIndexZoom(tileKey.m_zoomLevel); + CalcTilesCoverage(tileKey.GetGlobalRect(), lineZoom, + [this, &itTile, lineZoom](int tileX, int tileY) + { + itTile = m_index.find(TileKey(tileX, tileY, lineZoom)); + }); + if (itTile != m_index.end()) + return make_ref(itTile->second); + return nullptr; +} + void UserMarkGenerator::GenerateUserMarksGeometry(TileKey const & tileKey, ref_ptr textures) { - auto const itTile = m_index.find(TileKey(tileKey.m_x, tileKey.m_y, - std::min(tileKey.m_zoomLevel, scales::GetUpperScale()))); - if (itTile == m_index.end()) + auto const clippedTileKey = TileKey(tileKey.m_x, tileKey.m_y, ClipTileZoomByMaxDataZoom(tileKey.m_zoomLevel)); + auto marksGroups = GetUserMarksGroups(clippedTileKey); + auto linesGroups = GetUserLinesGroups(clippedTileKey); + + if (marksGroups == nullptr && linesGroups == nullptr) return; + uint32_t const kMaxSize = 65000; + dp::Batcher batcher(kMaxSize, kMaxSize); TUserMarksRenderData renderData; { - uint32_t const kMaxSize = 65000; - dp::Batcher batcher(kMaxSize, kMaxSize); dp::SessionGuard guard(batcher, [&tileKey, &renderData](dp::GLState const & state, drape_ptr && b) { renderData.emplace_back(state, std::move(b), tileKey); }); - MarksIDGroups & indexesGroups = *itTile->second; - for (auto & groupPair : indexesGroups) - { - MarkGroupID groupId = groupPair.first; - - if (m_groupsVisibility.find(groupId) == m_groupsVisibility.end()) - continue; - - CacheUserMarks(tileKey, textures, groupPair.second->m_marksID, m_marks, batcher); - CacheUserLines(tileKey, textures, groupPair.second->m_linesID, m_lines, batcher); - } + if (marksGroups != nullptr) + CacheUserMarks(tileKey, *marksGroups.get(), textures, batcher); + if (linesGroups != nullptr) + CacheUserLines(tileKey, *linesGroups.get(), textures, batcher); } m_flushFn(std::move(renderData)); } + +void UserMarkGenerator::CacheUserLines(TileKey const & tileKey, MarksIDGroups const & indexesGroups, + ref_ptr textures, dp::Batcher & batcher) +{ + for (auto & groupPair : indexesGroups) + { + MarkGroupID groupId = groupPair.first; + if (m_groupsVisibility.find(groupId) == m_groupsVisibility.end()) + continue; + + df::CacheUserLines(tileKey, textures, groupPair.second->m_linesID, m_lines, batcher); + } +} + +void UserMarkGenerator::CacheUserMarks(TileKey const & tileKey, MarksIDGroups const & indexesGroups, + ref_ptr textures, dp::Batcher & batcher) +{ + for (auto & groupPair : indexesGroups) + { + MarkGroupID groupId = groupPair.first; + if (m_groupsVisibility.find(groupId) == m_groupsVisibility.end()) + continue; + df::CacheUserMarks(tileKey, textures, groupPair.second->m_marksID, m_marks, batcher); + } +} + +int UserMarkGenerator::GetNearestLineIndexZoom(int zoom) const +{ + int nearestZoom = kLineIndexingLevels[0]; + for (int zoomLevel : kLineIndexingLevels) + { + if (zoomLevel <= zoom) + nearestZoom = zoomLevel; + else + break; + } + return nearestZoom; +} + } // namespace df diff --git a/drape_frontend/user_mark_generator.hpp b/drape_frontend/user_mark_generator.hpp index b72c8df71c..0013041f8f 100644 --- a/drape_frontend/user_mark_generator.hpp +++ b/drape_frontend/user_mark_generator.hpp @@ -39,6 +39,16 @@ private: ref_ptr GetIdCollection(TileKey const & tileKey, MarkGroupID groupId); void CleanIndex(); + int GetNearestLineIndexZoom(int zoom) const; + + ref_ptr GetUserMarksGroups(TileKey const & tileKey); + ref_ptr GetUserLinesGroups(TileKey const & tileKey); + + void CacheUserMarks(TileKey const & tileKey, MarksIDGroups const & indexesGroups, + ref_ptr textures, dp::Batcher & batcher); + void CacheUserLines(TileKey const & tileKey, MarksIDGroups const & indexesGroups, + ref_ptr textures, dp::Batcher & batcher); + std::unordered_set m_groupsVisibility; MarksIDGroups m_groups; diff --git a/drape_frontend/user_mark_shapes.cpp b/drape_frontend/user_mark_shapes.cpp index af3581e0f6..1e9cecde13 100644 --- a/drape_frontend/user_mark_shapes.cpp +++ b/drape_frontend/user_mark_shapes.cpp @@ -16,9 +16,17 @@ #include "indexer/feature_decl.hpp" #include "geometry/clipping.hpp" +#include "geometry/mercator.hpp" + +#include namespace df { +std::vector const kLineWidthZoomFactor = { +// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 0.3, 0.3, 0.3, 0.4, 0.5, 0.6, 0.7, 0.7, 0.7, 0.7, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 +}; +int const kLineSimplifyLevelEnd = 15; namespace { @@ -198,12 +206,41 @@ void CacheUserMarks(TileKey const & tileKey, ref_ptr texture } } +void ProcessSplineSegmentRects(m2::SharedSpline const & spline, double maxSegmentLength, + const std::function & func) +{ + double const splineFullLength = spline->GetLength(); + double length = 0; + while (length < splineFullLength) + { + m2::RectD splineRect; + + auto const itBegin = spline->GetPoint(length); + auto itEnd = spline->GetPoint(length + maxSegmentLength); + if (itEnd.BeginAgain()) + { + double const lastSegmentLength = spline->GetLengths().back(); + itEnd = spline->GetPoint(splineFullLength - lastSegmentLength / 2.0); + splineRect.Add(spline->GetPath().back()); + } + + spline->ForEachNode(itBegin, itEnd, [&splineRect](m2::PointD const & pt) + { + splineRect.Add(pt); + }); + + length += maxSegmentLength; + + if (!func(splineRect)) + return; + } +} + void CacheUserLines(TileKey const & tileKey, ref_ptr textures, IDCollection const & linesId, UserLinesRenderCollection & renderParams, dp::Batcher & batcher) { float const vs = static_cast(df::VisualParams::Instance().GetVisualScale()); - int const kLineSimplifyLevelEnd = 15; bool const simplify = tileKey.m_zoomLevel <= kLineSimplifyLevelEnd; double sqrScale; @@ -219,6 +256,23 @@ void CacheUserLines(TileKey const & tileKey, ref_ptr texture ASSERT(it != renderParams.end(), ()); UserLineRenderParams const & renderInfo = *it->second.get(); + m2::RectD const tileRect = tileKey.GetGlobalRect(); + + double const range = MercatorBounds::maxX - MercatorBounds::minX; + double const maxLength = range / (1 << (tileKey.m_zoomLevel - 1)); + + bool intersected = false; + ProcessSplineSegmentRects(renderInfo.m_spline, maxLength, + [&tileRect, &intersected](m2::RectD const & segmentRect) -> bool + { + if (segmentRect.IsIntersect(tileRect)) + intersected = true; + return !intersected; + }); + + if (!intersected) + continue; + m2::SharedSpline spline = renderInfo.m_spline; if (simplify) { @@ -240,7 +294,7 @@ void CacheUserLines(TileKey const & tileKey, ref_ptr texture } } - auto const clippedSplines = m2::ClipSplineByRect(tileKey.GetGlobalRect(), spline); + auto const clippedSplines = m2::ClipSplineByRect(tileRect, spline); for (auto const & clippedSpline : clippedSplines) { for (auto const & layer : renderInfo.m_layers) @@ -253,7 +307,7 @@ void CacheUserLines(TileKey const & tileKey, ref_ptr texture params.m_color = layer.m_color; params.m_depth = layer.m_depth; params.m_depthLayer = renderInfo.m_depthLayer; - params.m_width = layer.m_width * vs; + params.m_width = layer.m_width * vs * kLineWidthZoomFactor[tileKey.m_zoomLevel]; params.m_minVisibleScale = 1; params.m_rank = 0; diff --git a/drape_frontend/user_mark_shapes.hpp b/drape_frontend/user_mark_shapes.hpp index 299272e624..70431808f5 100644 --- a/drape_frontend/user_mark_shapes.hpp +++ b/drape_frontend/user_mark_shapes.hpp @@ -72,6 +72,9 @@ struct UserMarkRenderData using TUserMarksRenderData = std::vector; +void ProcessSplineSegmentRects(m2::SharedSpline const & spline, double maxSegmentLength, + std::function const & func); + void CacheUserMarks(TileKey const & tileKey, ref_ptr textures, IDCollection const & marksId, UserMarksRenderCollection & renderParams, dp::Batcher & batcher);