Files
MapLibreParticleLab/src/mbgl/layout/pattern_layout.hpp

137 lines
6.1 KiB
C++

#pragma once
#include <mbgl/layout/layout.hpp>
#include <mbgl/renderer/bucket_parameters.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/renderer/render_layer.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:
const uint32_t i;
std::unique_ptr<GeometryTileFeature> feature;
PatternLayerMap patterns;
};
template <class BucketType,
class LayerPropertiesType,
class PatternPropertyType,
class PossiblyEvaluatedLayoutPropertiesType = typename style::Properties<>::PossiblyEvaluated>
class PatternLayout : public Layout {
public:
PatternLayout(const BucketParameters& parameters,
const std::vector<Immutable<style::LayerProperties>>& group,
std::unique_ptr<GeometryTileLayer> sourceLayer_,
ImageDependencies& patternDependencies)
: 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<std::basic_string<char> >{ "", ""});
// 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.empty()){
hasPattern = true;
patternDependencies.emplace(constantPattern.to, ImageType::Pattern);
patternDependencies.emplace(constantPattern.from, 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() }))
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, PatternPropertyType::defaultValue());
const auto mid = patternProperty.evaluate(*feature, zoom, PatternPropertyType::defaultValue());
const auto max = patternProperty.evaluate(*feature, zoom + 1, PatternPropertyType::defaultValue());
patternDependencies.emplace(min.to, ImageType::Pattern);
patternDependencies.emplace(mid.to, ImageType::Pattern);
patternDependencies.emplace(max.to, ImageType::Pattern);
patternDependencyMap.emplace(layerId, PatternDependency {min.to, mid.to, max.to});
}
}
}
}
features.push_back({static_cast<uint32_t>(i), std::move(feature), patternDependencyMap});
}
};
~PatternLayout() final = default;
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, const bool) 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;
GeometryCollection geometries = feature->getGeometries();
bucket->addFeature(*feature, geometries, patternPositions, patterns);
featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID);
}
if (bucket->hasData()) {
for (const auto& pair : layerPropertiesMap) {
renderData.emplace(pair.first, LayerRenderData {bucket, pair.second});
}
}
};
private:
std::map<std::string, Immutable<style::LayerProperties>> layerPropertiesMap;
std::string bucketLeaderID;
const std::unique_ptr<GeometryTileLayer> sourceLayer;
std::vector<PatternFeature> features;
PossiblyEvaluatedLayoutPropertiesType layout;
const float zoom;
const uint32_t overscaling;
std::string sourceLayerID;
bool hasPattern;
};
} // namespace mbgl