[core] avoid symbol flickering when longitude is wrapped
This commit is contained in:
committed by
Ansis Brammanis
parent
60505b0317
commit
5e36f669ac
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user