209 lines
10 KiB
C++
209 lines
10 KiB
C++
#pragma once
|
|
#include <list>
|
|
#include <mbgl/geometry/feature_index.hpp>
|
|
#include <mbgl/layout/layout.hpp>
|
|
#include <mbgl/renderer/bucket_parameters.hpp>
|
|
#include <mbgl/renderer/render_layer.hpp>
|
|
#include <mbgl/style/expression/image.hpp>
|
|
#include <mbgl/style/layer_properties.hpp>
|
|
|
|
namespace mbgl {
|
|
|
|
class PatternDependency {
|
|
public:
|
|
std::string min;
|
|
std::string mid;
|
|
std::string max;
|
|
};
|
|
|
|
using PatternLayerMap = std::map<std::string, PatternDependency>;
|
|
|
|
class PatternFeature {
|
|
public:
|
|
PatternFeature(std::size_t i_,
|
|
std::unique_ptr<GeometryTileFeature> feature_,
|
|
PatternLayerMap patterns_,
|
|
float sortKey_ = 0.0f)
|
|
: i(i_),
|
|
feature(std::move(feature_)),
|
|
patterns(std::move(patterns_)),
|
|
sortKey(sortKey_) {}
|
|
|
|
friend bool operator<(const PatternFeature& lhs, const PatternFeature& rhs) { return lhs.sortKey < rhs.sortKey; }
|
|
|
|
std::size_t i;
|
|
std::unique_ptr<GeometryTileFeature> feature;
|
|
PatternLayerMap patterns;
|
|
float sortKey;
|
|
};
|
|
|
|
template <typename SortKeyPropertyType>
|
|
struct PatternFeatureInserter;
|
|
|
|
template <>
|
|
struct PatternFeatureInserter<void> {
|
|
template <typename PropertiesType>
|
|
static void insert(std::vector<PatternFeature>& features,
|
|
std::size_t index,
|
|
std::unique_ptr<GeometryTileFeature> feature,
|
|
PatternLayerMap patternDependencyMap,
|
|
float /*zoom*/,
|
|
const PropertiesType&,
|
|
const CanonicalTileID&) {
|
|
features.emplace_back(index, std::move(feature), std::move(patternDependencyMap));
|
|
}
|
|
};
|
|
|
|
template <class SortKeyPropertyType>
|
|
struct PatternFeatureInserter {
|
|
template <typename PropertiesType>
|
|
static void insert(std::vector<PatternFeature>& features,
|
|
std::size_t index,
|
|
std::unique_ptr<GeometryTileFeature> feature,
|
|
PatternLayerMap patternDependencyMap,
|
|
float zoom,
|
|
const PropertiesType& properties,
|
|
const CanonicalTileID& canonical) {
|
|
const auto& sortKeyProperty = properties.template get<SortKeyPropertyType>();
|
|
float sortKey = sortKeyProperty.evaluate(*feature, zoom, canonical, SortKeyPropertyType::defaultValue());
|
|
PatternFeature patternFeature{index, std::move(feature), std::move(patternDependencyMap), sortKey};
|
|
const auto lowerBound = std::lower_bound(features.cbegin(), features.cend(), patternFeature);
|
|
features.insert(lowerBound, std::move(patternFeature));
|
|
}
|
|
};
|
|
|
|
template <class BucketType,
|
|
class LayerPropertiesType,
|
|
class PatternPropertyType,
|
|
class LayoutPropertiesType = typename style::Properties<>,
|
|
class SortKeyPropertyType = void>
|
|
class PatternLayout : public Layout {
|
|
public:
|
|
PatternLayout(const BucketParameters& parameters,
|
|
const std::vector<Immutable<style::LayerProperties>>& group,
|
|
std::unique_ptr<GeometryTileLayer> sourceLayer_,
|
|
const LayoutParameters& layoutParameters)
|
|
: sourceLayer(std::move(sourceLayer_)),
|
|
zoom(parameters.tileID.overscaledZ),
|
|
overscaling(parameters.tileID.overscaleFactor()),
|
|
hasPattern(false) {
|
|
assert(!group.empty());
|
|
auto leaderLayerProperties = staticImmutableCast<LayerPropertiesType>(group.front());
|
|
layout = leaderLayerProperties->layerImpl().layout.evaluate(PropertyEvaluationParameters(zoom));
|
|
sourceLayerID = leaderLayerProperties->layerImpl().sourceLayer;
|
|
bucketLeaderID = leaderLayerProperties->layerImpl().id;
|
|
|
|
for (const auto& layerProperties : group) {
|
|
const std::string& layerId = layerProperties->baseImpl->id;
|
|
const auto& evaluated = style::getEvaluated<LayerPropertiesType>(layerProperties);
|
|
const auto& patternProperty = evaluated.template get<PatternPropertyType>();
|
|
const auto constantPattern = patternProperty.constantOr(Faded<style::expression::Image>{"", ""});
|
|
// determine if layer group has any layers that use *-pattern
|
|
// property and add constant pattern dependencies.
|
|
if (!patternProperty.isConstant()) {
|
|
hasPattern = true;
|
|
} else if (!constantPattern.to.id().empty()) {
|
|
hasPattern = true;
|
|
layoutParameters.imageDependencies.emplace(constantPattern.to.id(), ImageType::Pattern);
|
|
layoutParameters.imageDependencies.emplace(constantPattern.from.id(), ImageType::Pattern);
|
|
}
|
|
layerPropertiesMap.emplace(layerId, layerProperties);
|
|
}
|
|
|
|
const size_t featureCount = sourceLayer->featureCount();
|
|
for (size_t i = 0; i < featureCount; ++i) {
|
|
auto feature = sourceLayer->getFeature(i);
|
|
if (!leaderLayerProperties->layerImpl().filter(
|
|
style::expression::EvaluationContext(this->zoom, feature.get())
|
|
.withCanonicalTileID(¶meters.tileID.canonical)))
|
|
continue;
|
|
|
|
PatternLayerMap patternDependencyMap;
|
|
if (hasPattern) {
|
|
for (const auto& layerProperties : group) {
|
|
const std::string& layerId = layerProperties->baseImpl->id;
|
|
const auto it = layerPropertiesMap.find(layerId);
|
|
if (it != layerPropertiesMap.end()) {
|
|
const auto paint = static_cast<const LayerPropertiesType&>(*it->second).evaluated;
|
|
const auto& patternProperty = paint.template get<PatternPropertyType>();
|
|
if (!patternProperty.isConstant()) {
|
|
// For layers with non-data-constant pattern
|
|
// properties, evaluate their expression and add the
|
|
// patterns to the dependency vector
|
|
const auto min = patternProperty.evaluate(*feature,
|
|
zoom - 1,
|
|
layoutParameters.availableImages,
|
|
parameters.tileID.canonical,
|
|
PatternPropertyType::defaultValue());
|
|
const auto mid = patternProperty.evaluate(*feature,
|
|
zoom,
|
|
layoutParameters.availableImages,
|
|
parameters.tileID.canonical,
|
|
PatternPropertyType::defaultValue());
|
|
const auto max = patternProperty.evaluate(*feature,
|
|
zoom + 1,
|
|
layoutParameters.availableImages,
|
|
parameters.tileID.canonical,
|
|
PatternPropertyType::defaultValue());
|
|
|
|
layoutParameters.imageDependencies.emplace(min.to.id(), ImageType::Pattern);
|
|
layoutParameters.imageDependencies.emplace(mid.to.id(), ImageType::Pattern);
|
|
layoutParameters.imageDependencies.emplace(max.to.id(), ImageType::Pattern);
|
|
patternDependencyMap.emplace(layerId,
|
|
PatternDependency{min.to.id(), mid.to.id(), max.to.id()});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PatternFeatureInserter<SortKeyPropertyType>::insert(features,
|
|
i,
|
|
std::move(feature),
|
|
std::move(patternDependencyMap),
|
|
zoom,
|
|
layout,
|
|
parameters.tileID.canonical);
|
|
}
|
|
};
|
|
|
|
bool hasDependencies() const override { return hasPattern; }
|
|
|
|
void createBucket(const ImagePositions& patternPositions,
|
|
std::unique_ptr<FeatureIndex>& featureIndex,
|
|
std::unordered_map<std::string, LayerRenderData>& renderData,
|
|
const bool /*firstLoad*/,
|
|
const bool /*showCollisionBoxes*/,
|
|
const CanonicalTileID& canonical) override {
|
|
auto bucket = std::make_shared<BucketType>(layout, layerPropertiesMap, zoom, overscaling);
|
|
for (auto& patternFeature : features) {
|
|
const auto i = patternFeature.i;
|
|
std::unique_ptr<GeometryTileFeature> feature = std::move(patternFeature.feature);
|
|
const PatternLayerMap& patterns = patternFeature.patterns;
|
|
const GeometryCollection& geometries = feature->getGeometries();
|
|
|
|
bucket->addFeature(*feature, geometries, patternPositions, patterns, i, canonical);
|
|
featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID);
|
|
}
|
|
if (bucket->hasData()) {
|
|
for (const auto& pair : layerPropertiesMap) {
|
|
renderData.emplace(pair.first, LayerRenderData{bucket, pair.second});
|
|
}
|
|
}
|
|
};
|
|
|
|
protected:
|
|
std::map<std::string, Immutable<style::LayerProperties>> layerPropertiesMap;
|
|
std::string bucketLeaderID;
|
|
|
|
const std::unique_ptr<GeometryTileLayer> sourceLayer;
|
|
std::vector<PatternFeature> features;
|
|
typename LayoutPropertiesType::PossiblyEvaluated layout;
|
|
|
|
const float zoom;
|
|
const uint32_t overscaling;
|
|
std::string sourceLayerID;
|
|
bool hasPattern;
|
|
};
|
|
|
|
} // namespace mbgl
|