[core] Encapsulate placement code handling symbols sort ranges

This commit is contained in:
Mikhail Pozdnyakov
2020-02-28 14:11:15 +02:00
parent ffe95ec7d3
commit dea1063319
8 changed files with 49 additions and 54 deletions

View File

@@ -123,11 +123,6 @@ public:
static constexpr uint32_t invalidCrossTileID() { return std::numeric_limits<uint32_t>::max(); }
};
class SortKeyRange {
public:
float sortKey;
size_t symbolInstanceStart;
size_t symbolInstanceEnd;
};
using SymbolInstanceReferences = std::vector<std::reference_wrapper<const SymbolInstance>>;
} // namespace mbgl

View File

@@ -613,8 +613,8 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
iconType);
if (sortFeaturesByKey) {
if (sortKeyRanges.size() && sortKeyRanges.back().sortKey == feature.sortKey) {
sortKeyRanges.back().symbolInstanceEnd = symbolInstances.size();
if (!sortKeyRanges.empty() && sortKeyRanges.back().sortKey == feature.sortKey) {
sortKeyRanges.back().end = symbolInstances.size();
} else {
sortKeyRanges.push_back({feature.sortKey, symbolInstances.size() - 1, symbolInstances.size()});
}

View File

@@ -275,8 +275,8 @@ void SymbolBucket::sortFeatures(const float angle) {
featureSortOrder = std::move(symbolsSortOrder);
}
std::vector<std::reference_wrapper<const SymbolInstance>> SymbolBucket::getSortedSymbols(const float angle) const {
std::vector<std::reference_wrapper<const SymbolInstance>> result(symbolInstances.begin(), symbolInstances.end());
SymbolInstanceReferences SymbolBucket::getSortedSymbols(const float angle) const {
SymbolInstanceReferences result(symbolInstances.begin(), symbolInstances.end());
const float sin = std::sin(angle);
const float cos = std::cos(angle);
@@ -292,6 +292,15 @@ std::vector<std::reference_wrapper<const SymbolInstance>> SymbolBucket::getSorte
return result;
}
SymbolInstanceReferences SymbolBucket::getSymbols(const optional<SortKeyRange>& range) const {
if (!range) return SymbolInstanceReferences(symbolInstances.begin(), symbolInstances.end());
assert(range->start < range->end);
assert(range->end <= symbolInstances.size());
auto begin = symbolInstances.begin() + range->start;
auto end = symbolInstances.begin() + range->end;
return SymbolInstanceReferences(begin, end);
}
bool SymbolBucket::hasFormatSectionOverrides() const {
if (!hasFormatSectionOverrides_) {
hasFormatSectionOverrides_= SymbolLayerPaintPropertyOverrides::hasOverrides(layout->get<TextField>());

View File

@@ -1,16 +1,17 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/gfx/index_buffer.hpp>
#include <mbgl/programs/segment.hpp>
#include <mbgl/programs/symbol_program.hpp>
#include <mbgl/programs/collision_box_program.hpp>
#include <mbgl/text/glyph_range.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/gfx/vertex_buffer.hpp>
#include <mbgl/layout/symbol_feature.hpp>
#include <mbgl/layout/symbol_instance.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/programs/collision_box_program.hpp>
#include <mbgl/programs/segment.hpp>
#include <mbgl/programs/symbol_program.hpp>
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/text/glyph_range.hpp>
#include <mbgl/text/placement.hpp>
#include <vector>
@@ -97,8 +98,11 @@ public:
void sortFeatures(const float angle);
// The result contains references to the `symbolInstances` items, sorted by viewport Y.
std::vector<std::reference_wrapper<const SymbolInstance>> getSortedSymbols(const float angle) const;
// Returns references to the `symbolInstances` items, sorted by viewport Y.
SymbolInstanceReferences getSortedSymbols(const float angle) const;
// Returns references to the `symbolInstances` items, which belong to the `sortKeyRange` range;
// returns references to all the symbols if |sortKeyRange| is `nullopt`.
SymbolInstanceReferences getSymbols(const optional<SortKeyRange>& sortKeyRange = nullopt) const;
Immutable<style::SymbolLayoutProperties::PossiblyEvaluated> layout;
const std::string bucketLeaderID;
@@ -118,7 +122,7 @@ public:
bool hasUninitializedSymbols : 1;
std::vector<SymbolInstance> symbolInstances;
std::vector<SortKeyRange> sortKeyRanges;
const std::vector<SortKeyRange> sortKeyRanges;
struct PaintProperties {
SymbolIconProgram::Binders iconBinders;

View File

@@ -587,20 +587,16 @@ void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) {
auto featureIndex = static_cast<const GeometryTile*>(tile)->getFeatureIndex();
if (bucket->sortKeyRanges.empty()) {
placementData.push_back(
{*bucket, renderTile, featureIndex, firstInBucket, 0.0f, 0, bucket->symbolInstances.size()});
placementData.push_back({*bucket, renderTile, featureIndex, firstInBucket, nullopt});
} else {
for (const SortKeyRange& sortKeyRange : bucket->sortKeyRanges) {
LayerPlacementData layerData{*bucket,
renderTile,
featureIndex,
firstInBucket,
sortKeyRange.sortKey,
sortKeyRange.symbolInstanceStart,
sortKeyRange.symbolInstanceEnd};
auto sortPosition = std::upper_bound(placementData.cbegin(), placementData.cend(), layerData);
for (const auto& sortKeyRange : bucket->sortKeyRanges) {
LayerPlacementData layerData{*bucket, renderTile, featureIndex, firstInBucket, sortKeyRange};
auto sortPosition = std::upper_bound(
placementData.cbegin(), placementData.cend(), layerData, [](const auto& lhs, const auto& rhs) {
assert(lhs.sortKeyRange && rhs.sortKeyRange);
return lhs.sortKeyRange->sortKey < rhs.sortKeyRange->sortKey;
});
placementData.insert(sortPosition, std::move(layerData));
firstInBucket = false;
}
}

View File

@@ -28,18 +28,20 @@ public:
Immutable<style::LayerProperties> layerProperties;
};
class SortKeyRange {
public:
float sortKey;
size_t start;
size_t end;
};
class LayerPlacementData {
public:
friend bool operator<(const LayerPlacementData& lhs, const LayerPlacementData& rhs) {
return lhs.sortKey < rhs.sortKey;
}
std::reference_wrapper<Bucket> bucket;
std::reference_wrapper<const RenderTile> tile;
std::shared_ptr<FeatureIndex> featureIndex;
bool firstInBucket;
float sortKey;
size_t symbolInstanceStart;
size_t symbolInstanceEnd;
optional<SortKeyRange> sortKeyRange;
};
class LayerPrepareParameters {

View File

@@ -113,12 +113,7 @@ void Placement::placeLayer(const RenderLayer& layer) {
std::set<uint32_t> seenCrossTileIDs;
for (const auto& item : layer.getPlacementData()) {
Bucket& bucket = item.bucket;
BucketPlacementParameters params{item.tile,
layer.baseImpl->source,
item.featureIndex,
item.sortKey,
item.symbolInstanceStart,
item.symbolInstanceEnd};
BucketPlacementParameters params{item.tile, layer.baseImpl->source, item.featureIndex, item.sortKeyRange};
bucket.place(*this, params, seenCrossTileIDs);
}
}
@@ -661,12 +656,8 @@ void Placement::placeBucket(const SymbolBucket& bucket,
}
} else {
auto beginIt = bucket.symbolInstances.begin() + params.symbolInstanceStart;
auto endIt = bucket.symbolInstances.begin() + params.symbolInstanceEnd;
assert(params.symbolInstanceStart < params.symbolInstanceEnd);
assert(params.symbolInstanceEnd <= bucket.symbolInstances.size());
for (auto it = beginIt; it != endIt; ++it) {
placeSymbol(*it);
for (const SymbolInstance& symbol : bucket.getSymbols(params.sortKeyRange)) {
placeSymbol(symbol);
}
}

View File

@@ -91,9 +91,7 @@ public:
const RenderTile& tile;
std::string sourceId;
std::shared_ptr<FeatureIndex> featureIndex;
float sortKey;
size_t symbolInstanceStart;
size_t symbolInstanceEnd;
optional<SortKeyRange> sortKeyRange;
};
class Placement;