From 67f01c45e7265eb695113dd32062d99c87adaeab Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 21 Feb 2019 11:37:06 +0200 Subject: [core] Filter out child tiles that overlap with parent render tile --- src/mbgl/renderer/layers/render_circle_layer.cpp | 42 ++++++++++++++++++++++++ src/mbgl/renderer/layers/render_circle_layer.hpp | 1 + 2 files changed, 43 insertions(+) (limited to 'src') diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index e96dee0cf5..d6e6fe2c19 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -19,6 +19,21 @@ inline const style::CircleLayer::Impl& impl(const Immutable& return static_cast(*impl); } +namespace { + +template +bool isCoveredByParent(const UnwrappedTileID& child, Iterator begin, Iterator end) { + for (auto it = begin; it != end; ++it) { + const auto& tileId = it->get().id; + if (child != tileId && child.isChildOf(tileId)) { + return true; + } + } + return false; +} + +} // namespace + RenderCircleLayer::RenderCircleLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), unevaluated(impl(baseImpl).paint.untransitioned()) { @@ -187,4 +202,31 @@ bool RenderCircleLayer::queryIntersectsFeature( return false; } +void RenderCircleLayer::setRenderTiles(RenderTiles tiles_, const TransformState& state) { + RenderLayer::setRenderTiles(std::move(tiles_), state); + + // Tiles are sorted by tile id / zoom level, if first and last tiles are from different + // zoom levels, check whether tile vector contains parents covering children area. + // This might happen when map is panned (or zoomed) and missing tile is not yet loaded, + // thus, cached parent tile is used to cover missing area, therefore, loaded child tiles + // will be drawn together with the parent. + + if (renderTiles.size() > 1 && + renderTiles.front().get().id.canonical.z != renderTiles.back().get().id.canonical.z) { + + RenderTiles filtered; + filtered.reserve(renderTiles.size()); + + auto lowerBound = renderTiles.end(); + for (auto it = renderTiles.rbegin(); it != renderTiles.rend(); ++it) { + if (!isCoveredByParent(it->get().id, renderTiles.begin(), --lowerBound)) { + filtered.emplace_back(it->get()); + } + } + + std::reverse(filtered.begin(), filtered.end()); + renderTiles = std::move(filtered); + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index fbe67c91ac..383ca8b88f 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -17,6 +17,7 @@ private: bool hasTransition() const override; bool hasCrossfade() const override; void render(PaintParameters&, RenderSource*) override; + void setRenderTiles(RenderTiles tiles, const TransformState&) override; bool queryIntersectsFeature( const GeometryCoordinates&, -- cgit v1.2.1