diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-02-21 11:37:06 +0200 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-02-25 13:22:05 +0200 |
commit | f44d0da6d1bb6e94093bb3199a1689ca80d39693 (patch) | |
tree | 14e1c4d00434195c524144448b33e6e1c696bf91 | |
parent | fee22273be2d33049311de72ff6bf973b6b05164 (diff) | |
download | qtlocation-mapboxgl-f44d0da6d1bb6e94093bb3199a1689ca80d39693.tar.gz |
[core] Filter out child tiles that overlap with parent render tile
-rw-r--r-- | src/mbgl/renderer/layers/render_circle_layer.cpp | 42 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_circle_layer.hpp | 1 |
2 files changed, 43 insertions, 0 deletions
diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index 65550991a9..81509c1882 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -14,6 +14,19 @@ namespace mbgl { using namespace style; +namespace { +template <typename Iterator> +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<style::CircleLayer::Impl> _impl) : RenderLayer(std::move(_impl)), unevaluated(impl().paint.untransitioned()) { @@ -187,4 +200,33 @@ bool RenderCircleLayer::queryIntersectsFeature( return false; } +RenderLayer::RenderTiles RenderCircleLayer::filterRenderTiles(RenderTiles tiles_) const { + RenderTiles tiles = RenderLayer::filterRenderTiles(tiles_); + + // 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 (tiles.size() > 1 && + tiles.front().get().id.canonical.z != tiles.back().get().id.canonical.z) { + + RenderTiles filtered; + filtered.reserve(tiles.size()); + + auto lowerBound = tiles.end(); + for (auto it = tiles.rbegin(); it != tiles.rend(); ++it) { + if (!isCoveredByParent(it->get().id, tiles.begin(), --lowerBound)) { + filtered.emplace_back(it->get()); + } + } + + std::reverse(filtered.begin(), filtered.end()); + return filtered; + } + + return tiles; +} + } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp index 5515aa0452..552299f166 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.hpp +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -16,6 +16,7 @@ public: bool hasTransition() const override; bool hasCrossfade() const override; void render(PaintParameters&, RenderSource*) override; + RenderTiles filterRenderTiles(RenderTiles) const override; bool queryIntersectsFeature( const GeometryCoordinates&, |