diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-04-18 18:05:53 +0300 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-05-08 12:21:47 +0300 |
commit | ef48d53e78573c30d543a5fa84a7d524c950a2f3 (patch) | |
tree | 9e66018861eec8960844b6c3ca7471ca07c2c2f5 /src/mbgl/renderer/buckets/symbol_bucket.cpp | |
parent | f703c6f2552245f11eff8e66b9613e7d28ee193e (diff) | |
download | qtlocation-mapboxgl-ef48d53e78573c30d543a5fa84a7d524c950a2f3.tar.gz |
[core] Placement order matches viewport-y sort
Symbols are placed accordingly to their viewport Y order,
if the style `symbol-z-order` is set to `viewport-y`.
This improves rendering of symbol layers, where icons are allowed
to overlap but not text.
Diffstat (limited to 'src/mbgl/renderer/buckets/symbol_bucket.cpp')
-rw-r--r-- | src/mbgl/renderer/buckets/symbol_bucket.cpp | 49 |
1 files changed, 22 insertions, 27 deletions
diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index c7eb7c6e5c..243cd4ebce 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -182,38 +182,16 @@ void SymbolBucket::sortFeatures(const float angle) { sortUploaded = false; uploaded = false; - // If the symbols are allowed to overlap sort them by their vertical screen position. - // The index array buffer is rewritten to reference the (unchanged) vertices in the - // sorted order. - - // To avoid sorting the actual symbolInstance array we sort an array of indexes. - std::vector<size_t> symbolInstanceIndexes; - symbolInstanceIndexes.reserve(symbolInstances.size()); - for (size_t i = 0; i < symbolInstances.size(); i++) { - symbolInstanceIndexes.push_back(i); - } - - const float sin = std::sin(angle); - const float cos = std::cos(angle); - - std::sort(symbolInstanceIndexes.begin(), symbolInstanceIndexes.end(), [sin, cos, this](size_t &aIndex, size_t &bIndex) { - const SymbolInstance& a = symbolInstances[aIndex]; - const SymbolInstance& b = symbolInstances[bIndex]; - const auto aRotated = static_cast<int32_t>(::lround(sin * a.anchor.point.x + cos * a.anchor.point.y)); - const auto bRotated = static_cast<int32_t>(::lround(sin * b.anchor.point.x + cos * b.anchor.point.y)); - return aRotated != bRotated ? - aRotated < bRotated : - a.dataFeatureIndex > b.dataFeatureIndex; - }); - text.triangles.clear(); icon.triangles.clear(); featureSortOrder = std::make_unique<std::vector<size_t>>(); - featureSortOrder->reserve(symbolInstanceIndexes.size()); + featureSortOrder->reserve(symbolInstances.size()); - for (auto i : symbolInstanceIndexes) { - const SymbolInstance& symbolInstance = symbolInstances[i]; + // If the symbols are allowed to overlap sort them by their vertical screen position. + // The index array buffer is rewritten to reference the (unchanged) vertices in the + // sorted order. + for (const SymbolInstance& symbolInstance : getSortedSymbols(angle)) { featureSortOrder->push_back(symbolInstance.dataFeatureIndex); if (symbolInstance.placedRightTextIndex) { @@ -238,6 +216,23 @@ void SymbolBucket::sortFeatures(const float angle) { } } +std::vector<std::reference_wrapper<SymbolInstance>> SymbolBucket::getSortedSymbols(const float angle) { + std::vector<std::reference_wrapper<SymbolInstance>> result(symbolInstances.begin(), symbolInstances.end()); + const float sin = std::sin(angle); + const float cos = std::cos(angle); + + std::sort(result.begin(), result.end(), [sin, cos](const SymbolInstance& a, const SymbolInstance& b) { + const auto aRotated = ::lround(sin * a.anchor.point.x + cos * a.anchor.point.y); + const auto bRotated = ::lround(sin * b.anchor.point.x + cos * b.anchor.point.y); + if (aRotated != bRotated) { + return aRotated < bRotated; + } + return a.dataFeatureIndex > b.dataFeatureIndex; // aRotated == bRotated + }); + + return result; +} + bool SymbolBucket::hasFormatSectionOverrides() const { if (!hasFormatSectionOverrides_) { hasFormatSectionOverrides_= SymbolLayerPaintPropertyOverrides::hasOverrides(layout.get<TextField>()); |