summaryrefslogtreecommitdiff
path: root/src/mbgl/text
diff options
context:
space:
mode:
authorChris Loer <chris.loer@gmail.com>2018-01-16 12:38:27 -0800
committerChris Loer <chris.loer@mapbox.com>2018-01-17 12:49:30 -0800
commitb3d3ab0e31d251cf39dfa78dfbc0661b8819a8ab (patch)
treeb7c33de0d95b31e5852f587d1fedc3cc8861acc0 /src/mbgl/text
parentfa3dee93f8161f9ee3279a762122d1a3ddd41c2e (diff)
downloadqtlocation-mapboxgl-b3d3ab0e31d251cf39dfa78dfbc0661b8819a8ab.tar.gz
[core] Prevent symbols at the same zoom from sharing a crossTileID.
Port of GL JS PR #5994. Fixes issue #10844, which would allow multiple symbols in a tile to share the same crossTileID as one of their duplicate parent-tile symbols. Once the symbols shared a crossTileID, they would permanently remain "duplicates" of each other, even after increasing zoom level allowed the CrossTileSymbolIndex to distinguish between them.
Diffstat (limited to 'src/mbgl/text')
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.cpp36
-rw-r--r--src/mbgl/text/cross_tile_symbol_index.hpp8
2 files changed, 35 insertions, 9 deletions
diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp
index 30d265d885..8f4956c4ea 100644
--- a/src/mbgl/text/cross_tile_symbol_index.cpp
+++ b/src/mbgl/text/cross_tile_symbol_index.cpp
@@ -24,7 +24,7 @@ Point<int64_t> TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstan
};
}
-void TileLayerIndex::findMatches(std::vector<SymbolInstance>& symbolInstances, const OverscaledTileID& newCoord) {
+void TileLayerIndex::findMatches(std::vector<SymbolInstance>& symbolInstances, const OverscaledTileID& newCoord, std::set<uint32_t>& zoomCrossTileIDs) {
float tolerance = coord.canonical.z < newCoord.canonical.z ? 1 : std::pow(2, coord.canonical.z - newCoord.canonical.z);
for (auto& symbolInstance : symbolInstances) {
@@ -45,8 +45,12 @@ void TileLayerIndex::findMatches(std::vector<SymbolInstance>& symbolInstances, c
// Return any symbol with the same keys whose coordinates are within 1
// grid unit. (with a 4px grid, this covers a 12px by 12px area)
if (std::abs(thisTileSymbol.coord.x - scaledSymbolCoord.x) <= tolerance &&
- std::abs(thisTileSymbol.coord.y - scaledSymbolCoord.y) <= tolerance) {
-
+ std::abs(thisTileSymbol.coord.y - scaledSymbolCoord.y) <= tolerance &&
+ zoomCrossTileIDs.find(thisTileSymbol.crossTileID) == zoomCrossTileIDs.end()) {
+ // Once we've marked ourselves duplicate against this parent symbol,
+ // don't let any other symbols at the same zoom level duplicate against
+ // the same parent (see issue #10844)
+ zoomCrossTileIDs.insert(thisTileSymbol.crossTileID);
symbolInstance.crossTileID = thisTileSymbol.crossTileID;
break;
}
@@ -60,8 +64,16 @@ CrossTileSymbolLayerIndex::CrossTileSymbolLayerIndex() {
bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, SymbolBucket& bucket, uint32_t& maxCrossTileID) {
auto thisZoomIndexes = indexes[tileID.overscaledZ];
auto previousIndex = thisZoomIndexes.find(tileID);
- if (previousIndex != thisZoomIndexes.end() && previousIndex->second.bucketInstanceId == bucket.bucketInstanceId) {
- return false;
+ if (previousIndex != thisZoomIndexes.end()) {
+ if (previousIndex->second.bucketInstanceId == bucket.bucketInstanceId) {
+ return false;
+ } else {
+ // We're replacing this bucket with an updated version
+ // Remove the old bucket's "used crossTileIDs" now so that the new bucket can claim them.
+ // We have to keep the old index entries themselves until the end of 'addBucket' so
+ // that we can copy them with 'findMatches'.
+ removeBucketCrossTileIDs(tileID.overscaledZ, previousIndex->second);
+ }
}
for (auto& symbolInstance: bucket.symbolInstances) {
@@ -74,14 +86,14 @@ bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, Symbol
if (zoom > tileID.overscaledZ) {
for (auto& childIndex : zoomIndexes) {
if (childIndex.second.coord.isChildOf(tileID)) {
- childIndex.second.findMatches(bucket.symbolInstances, tileID);
+ childIndex.second.findMatches(bucket.symbolInstances, tileID, usedCrossTileIDs[tileID.overscaledZ]);
}
}
} else {
auto parentTileID = tileID.scaledTo(zoom);
auto parentIndex = zoomIndexes.find(parentTileID);
if (parentIndex != zoomIndexes.end()) {
- parentIndex->second.findMatches(bucket.symbolInstances, tileID);
+ parentIndex->second.findMatches(bucket.symbolInstances, tileID, usedCrossTileIDs[tileID.overscaledZ]);
}
}
}
@@ -90,6 +102,7 @@ bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, Symbol
if (!symbolInstance.crossTileID) {
// symbol did not match any known symbol, assign a new id
symbolInstance.crossTileID = ++maxCrossTileID;
+ usedCrossTileIDs[tileID.overscaledZ].insert(symbolInstance.crossTileID);
}
}
@@ -99,11 +112,20 @@ bool CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& tileID, Symbol
return true;
}
+void CrossTileSymbolLayerIndex::removeBucketCrossTileIDs(uint8_t zoom, const TileLayerIndex& removedBucket) {
+ for (auto key : removedBucket.indexedSymbolInstances) {
+ for (auto indexedSymbolInstance : key.second) {
+ usedCrossTileIDs[zoom].erase(indexedSymbolInstance.crossTileID);
+ }
+ }
+}
+
bool CrossTileSymbolLayerIndex::removeStaleBuckets(const std::unordered_set<uint32_t>& currentIDs) {
bool tilesChanged = false;
for (auto& zoomIndexes : indexes) {
for (auto it = zoomIndexes.second.begin(); it != zoomIndexes.second.end();) {
if (!currentIDs.count(it->second.bucketInstanceId)) {
+ removeBucketCrossTileIDs(zoomIndexes.first, it->second);
it = zoomIndexes.second.erase(it);
tilesChanged = true;
} else {
diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp
index 995e0061b9..5abcde241c 100644
--- a/src/mbgl/text/cross_tile_symbol_index.hpp
+++ b/src/mbgl/text/cross_tile_symbol_index.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/optional.hpp>
#include <map>
+#include <set>
#include <vector>
#include <string>
#include <memory>
@@ -32,7 +33,7 @@ public:
TileLayerIndex(OverscaledTileID coord, std::vector<SymbolInstance>&, uint32_t bucketInstanceId);
Point<int64_t> getScaledCoordinates(SymbolInstance&, const OverscaledTileID&);
- void findMatches(std::vector<SymbolInstance>&, const OverscaledTileID&);
+ void findMatches(std::vector<SymbolInstance>&, const OverscaledTileID&, std::set<uint32_t>&);
OverscaledTileID coord;
uint32_t bucketInstanceId;
@@ -45,7 +46,10 @@ public:
bool addBucket(const OverscaledTileID&, SymbolBucket&, uint32_t& maxCrossTileID);
bool removeStaleBuckets(const std::unordered_set<uint32_t>& currentIDs);
private:
- std::map<uint8_t,std::map<OverscaledTileID,TileLayerIndex>> indexes;
+ 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;
};
class CrossTileSymbolIndex {