summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnsis Brammanis <ansis@mapbox.com>2018-05-17 11:30:04 -0400
committerAnsis Brammanis <ansis.brammanis@gmail.com>2018-05-22 14:58:11 -0400
commit5e36f669acd756d26e2dfa6db1a2a94bd1ceb701 (patch)
tree553489b2de586e872c9c89d7d4038d5e93f5ce2d
parent60505b03174b5ec02ae723beafa7683f6ed54a62 (diff)
downloadqtlocation-mapboxgl-5e36f669acd756d26e2dfa6db1a2a94bd1ceb701.tar.gz
[core] avoid symbol flickering when longitude is wrapped
-rw-r--r--include/mbgl/tile/tile_id.hpp11
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp3
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.cpp30
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.hpp4
4 files changed, 42 insertions, 6 deletions
diff --git a/include/mbgl/tile/tile_id.hpp b/include/mbgl/tile/tile_id.hpp
index 11fb5ce537..3b52596f6c 100644
--- a/include/mbgl/tile/tile_id.hpp
+++ b/include/mbgl/tile/tile_id.hpp
@@ -58,10 +58,11 @@ public:
uint32_t overscaleFactor() const;
OverscaledTileID scaledTo(uint8_t z) const;
UnwrappedTileID toUnwrapped() const;
+ OverscaledTileID unwrapTo(int16_t wrap);
- const uint8_t overscaledZ;
- const int16_t wrap;
- const CanonicalTileID canonical;
+ uint8_t overscaledZ;
+ int16_t wrap;
+ CanonicalTileID canonical;
};
::std::ostream& operator<<(::std::ostream& os, const OverscaledTileID& rhs);
@@ -191,6 +192,10 @@ inline UnwrappedTileID OverscaledTileID::toUnwrapped() const {
return { wrap, canonical };
}
+inline OverscaledTileID OverscaledTileID::unwrapTo(int16_t newWrap) {
+ return { overscaledZ, newWrap, canonical };
+}
+
inline UnwrappedTileID::UnwrappedTileID(uint8_t z_, int64_t x_, int64_t y_)
: wrap((x_ < 0 ? x_ - (1ll << z_) + 1 : x_) / (1ll << z_)),
canonical(
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index 4380ef24a1..ca9e809977 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -380,7 +380,8 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
}
for (auto it = order.rbegin(); it != order.rend(); ++it) {
if (it->layer.is<RenderSymbolLayer>()) {
- if (crossTileSymbolIndex.addLayer(*it->layer.as<RenderSymbolLayer>())) symbolBucketsChanged = true;
+ const float lng = parameters.state.getLatLng().longitude();
+ if (crossTileSymbolIndex.addLayer(*it->layer.as<RenderSymbolLayer>(), lng)) symbolBucketsChanged = true;
}
}
diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp
index b0c3511ce3..8df26ca117 100644
--- a/src/mbgl/text/cross_tile_symbol_index.cpp
+++ b/src/mbgl/text/cross_tile_symbol_index.cpp
@@ -61,6 +61,32 @@ void TileLayerIndex::findMatches(std::vector<SymbolInstance>& symbolInstances, c
CrossTileSymbolLayerIndex::CrossTileSymbolLayerIndex() {
}
+/*
+ * Sometimes when a user pans across the antimeridian the longitude value gets wrapped.
+ * To prevent labels from flashing out and in we adjust the tileID values in the indexes
+ * so that they match the new wrapped version of the map.
+ */
+void CrossTileSymbolLayerIndex::handleWrapJump(float newLng) {
+
+ const int wrapDelta = ::round((newLng - lng) / 360);
+ if (wrapDelta != 0) {
+ std::map<uint8_t, std::map<OverscaledTileID,TileLayerIndex>> newIndexes;
+ for (auto& zoomIndex : indexes) {
+ std::map<OverscaledTileID,TileLayerIndex> newZoomIndex;
+ for (auto& index : zoomIndex.second) {
+ // change the tileID's wrap and move its index
+ index.second.coord = index.second.coord.unwrapTo(index.second.coord.wrap + wrapDelta);
+ newZoomIndex.emplace(index.second.coord, std::move(index.second));
+ }
+ newIndexes.emplace(zoomIndex.first, std::move(newZoomIndex));
+ }
+
+ indexes = std::move(newIndexes);
+ }
+
+ lng = newLng;
+}
+
bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, SymbolBucket& bucket, uint32_t& maxCrossTileID) {
const auto& thisZoomIndexes = indexes[tileID.overscaledZ];
auto previousIndex = thisZoomIndexes.find(tileID);
@@ -138,13 +164,15 @@ bool CrossTileSymbolLayerIndex::removeStaleBuckets(const std::unordered_set<uint
CrossTileSymbolIndex::CrossTileSymbolIndex() {}
-bool CrossTileSymbolIndex::addLayer(RenderSymbolLayer& symbolLayer) {
+bool CrossTileSymbolIndex::addLayer(RenderSymbolLayer& symbolLayer, float lng) {
auto& layerIndex = layerIndexes[symbolLayer.getID()];
bool symbolBucketsChanged = false;
std::unordered_set<uint32_t> currentBucketIDs;
+ layerIndex.handleWrapJump(lng);
+
for (RenderTile& renderTile : symbolLayer.renderTiles) {
if (!renderTile.tile.isRenderable()) {
continue;
diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp
index 541c2e3661..051573e1d2 100644
--- a/src/mbgl/text/cross_tile_symbol_index.hpp
+++ b/src/mbgl/text/cross_tile_symbol_index.hpp
@@ -45,18 +45,20 @@ public:
CrossTileSymbolLayerIndex();
bool addBucket(const OverscaledTileID&, SymbolBucket&, uint32_t& maxCrossTileID);
bool removeStaleBuckets(const std::unordered_set<uint32_t>& currentIDs);
+ void handleWrapJump(float newLng);
private:
void removeBucketCrossTileIDs(uint8_t zoom, const TileLayerIndex& removedBucket);
std::map<uint8_t, std::map<OverscaledTileID,TileLayerIndex>> indexes;
std::map<uint8_t, std::set<uint32_t>> usedCrossTileIDs;
+ float lng = 0;
};
class CrossTileSymbolIndex {
public:
CrossTileSymbolIndex();
- bool addLayer(RenderSymbolLayer&);
+ bool addLayer(RenderSymbolLayer&, float lng);
void pruneUnusedLayers(const std::set<std::string>&);
void reset();