[core] Support [within expression] with layout property
This commit is contained in:
@@ -73,6 +73,20 @@ public:
|
||||
finalDefaultValue);
|
||||
}
|
||||
|
||||
T evaluate(const GeometryTileFeature& feature, const CanonicalTileID& canonical, T finalDefaultValue) const {
|
||||
return evaluate(expression::EvaluationContext(&feature).withCanonicalTileID(&canonical), finalDefaultValue);
|
||||
}
|
||||
|
||||
T evaluate(const GeometryTileFeature& feature,
|
||||
const std::set<std::string>& availableImages,
|
||||
const CanonicalTileID& canonical,
|
||||
T finalDefaultValue) const {
|
||||
return evaluate(expression::EvaluationContext(&feature)
|
||||
.withAvailableImages(&availableImages)
|
||||
.withCanonicalTileID(&canonical),
|
||||
finalDefaultValue);
|
||||
}
|
||||
|
||||
T evaluate(float zoom, const GeometryTileFeature& feature, T finalDefaultValue) const {
|
||||
return evaluate(expression::EvaluationContext(zoom, &feature), finalDefaultValue);
|
||||
}
|
||||
@@ -85,6 +99,25 @@ public:
|
||||
finalDefaultValue);
|
||||
}
|
||||
|
||||
T evaluate(float zoom,
|
||||
const GeometryTileFeature& feature,
|
||||
const std::set<std::string>& availableImages,
|
||||
const CanonicalTileID& canonical,
|
||||
T finalDefaultValue) const {
|
||||
return evaluate(expression::EvaluationContext(zoom, &feature)
|
||||
.withAvailableImages(&availableImages)
|
||||
.withCanonicalTileID(&canonical),
|
||||
finalDefaultValue);
|
||||
}
|
||||
|
||||
T evaluate(float zoom,
|
||||
const GeometryTileFeature& feature,
|
||||
const CanonicalTileID& canonical,
|
||||
T finalDefaultValue) const {
|
||||
return evaluate(expression::EvaluationContext(zoom, &feature).withCanonicalTileID(&canonical),
|
||||
finalDefaultValue);
|
||||
}
|
||||
|
||||
T evaluate(float zoom, const GeometryTileFeature& feature, const FeatureState& state, T finalDefaultValue) const {
|
||||
assert(!isFeatureConstant());
|
||||
return evaluate(expression::EvaluationContext(zoom, &feature, &state), finalDefaultValue);
|
||||
|
||||
@@ -132,6 +132,5 @@
|
||||
"render-tests/text-variable-anchor/left-top-right-buttom-offset-tile-map-mode":"https://github.com/mapbox/mapbox-gl-js/pull/9202",
|
||||
"render-tests/line-pattern/with-dasharray":"https://github.com/mapbox/mapbox-gl-js/pull/9189",
|
||||
"render-tests/symbol-sort-key/placement-tile-boundary-right-then-left": "https://github.com/mapbox/mapbox-gl-js/pull/9054",
|
||||
"render-tests/line-dasharray/zero-length-gap":"https://github.com/mapbox/mapbox-gl-js/pull/9246",
|
||||
"render-tests/within/layout-text": "TODO: Fix by enabling `within` expreesion with layout property"
|
||||
"render-tests/line-dasharray/zero-length-gap":"https://github.com/mapbox/mapbox-gl-js/pull/9246"
|
||||
}
|
||||
|
||||
@@ -45,7 +45,8 @@ struct PatternFeatureInserter<void> {
|
||||
std::unique_ptr<GeometryTileFeature> feature,
|
||||
PatternLayerMap patternDependencyMap,
|
||||
float /*zoom*/,
|
||||
const PropertiesType&) {
|
||||
const PropertiesType&,
|
||||
const CanonicalTileID&) {
|
||||
features.emplace_back(index, std::move(feature), std::move(patternDependencyMap));
|
||||
}
|
||||
};
|
||||
@@ -58,9 +59,10 @@ struct PatternFeatureInserter {
|
||||
std::unique_ptr<GeometryTileFeature> feature,
|
||||
PatternLayerMap patternDependencyMap,
|
||||
float zoom,
|
||||
const PropertiesType& properties) {
|
||||
const PropertiesType& properties,
|
||||
const CanonicalTileID& canonical) {
|
||||
const auto& sortKeyProperty = properties.template get<SortKeyPropertyType>();
|
||||
float sortKey = sortKeyProperty.evaluate(*feature, zoom, SortKeyPropertyType::defaultValue());
|
||||
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));
|
||||
@@ -127,12 +129,17 @@ public:
|
||||
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 mid = patternProperty.evaluate(
|
||||
*feature, zoom, layoutParameters.availableImages, 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);
|
||||
@@ -145,14 +152,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
PatternFeatureInserter<SortKeyPropertyType>::insert(
|
||||
features, i, std::move(feature), std::move(patternDependencyMap), zoom, layout);
|
||||
PatternFeatureInserter<SortKeyPropertyType>::insert(features,
|
||||
i,
|
||||
std::move(feature),
|
||||
std::move(patternDependencyMap),
|
||||
zoom,
|
||||
layout,
|
||||
parameters.tileID.canonical);
|
||||
}
|
||||
};
|
||||
|
||||
bool hasDependencies() const override {
|
||||
return hasPattern;
|
||||
}
|
||||
bool hasDependencies() const override { return hasPattern; }
|
||||
|
||||
void createBucket(const ImagePositions& patternPositions,
|
||||
std::unique_ptr<FeatureIndex>& featureIndex,
|
||||
|
||||
@@ -86,6 +86,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
|
||||
sourceLayer(std::move(sourceLayer_)),
|
||||
overscaling(parameters.tileID.overscaleFactor()),
|
||||
zoom(parameters.tileID.overscaledZ),
|
||||
canonicalID(parameters.tileID.canonical),
|
||||
mode(parameters.mode),
|
||||
pixelRatio(parameters.pixelRatio),
|
||||
tileSize(util::tileSize * overscaling),
|
||||
@@ -141,9 +142,9 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
|
||||
ft.index = i;
|
||||
|
||||
if (hasText) {
|
||||
auto formatted = layout->evaluate<TextField>(zoom, ft, layoutParameters.availableImages);
|
||||
auto textTransform = layout->evaluate<TextTransform>(zoom, ft);
|
||||
FontStack baseFontStack = layout->evaluate<TextFont>(zoom, ft);
|
||||
auto formatted = layout->evaluate<TextField>(zoom, ft, layoutParameters.availableImages, canonicalID);
|
||||
auto textTransform = layout->evaluate<TextTransform>(zoom, ft, canonicalID);
|
||||
FontStack baseFontStack = layout->evaluate<TextFont>(zoom, ft, canonicalID);
|
||||
|
||||
ft.formattedText = TaggedString();
|
||||
for (const auto & section : formatted.sections) {
|
||||
@@ -188,13 +189,13 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
|
||||
}
|
||||
|
||||
if (hasIcon) {
|
||||
ft.icon = layout->evaluate<IconImage>(zoom, ft, layoutParameters.availableImages);
|
||||
ft.icon = layout->evaluate<IconImage>(zoom, ft, layoutParameters.availableImages, canonicalID);
|
||||
layoutParameters.imageDependencies.emplace(ft.icon->id(), ImageType::Icon);
|
||||
}
|
||||
|
||||
if (ft.formattedText || ft.icon) {
|
||||
if (sortFeaturesByKey) {
|
||||
ft.sortKey = layout->evaluate<SymbolSortKey>(zoom, ft);
|
||||
ft.sortKey = layout->evaluate<SymbolSortKey>(zoom, ft, canonicalID);
|
||||
const auto lowerBound = std::lower_bound(features.begin(), features.end(), ft);
|
||||
features.insert(lowerBound, std::move(ft));
|
||||
} else {
|
||||
@@ -355,14 +356,16 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap,
|
||||
ShapedTextOrientations shapedTextOrientations;
|
||||
optional<PositionedIcon> shapedIcon;
|
||||
std::array<float, 2> textOffset{{0.0f, 0.0f}};
|
||||
const float layoutTextSize = layout->evaluate<TextSize>(zoom + 1, feature);
|
||||
const float layoutTextSizeAtBucketZoomLevel = layout->evaluate<TextSize>(zoom, feature);
|
||||
const float layoutIconSize = layout->evaluate<IconSize>(zoom + 1, feature);
|
||||
const float layoutTextSize = layout->evaluate<TextSize>(zoom + 1, feature, canonicalID);
|
||||
const float layoutTextSizeAtBucketZoomLevel = layout->evaluate<TextSize>(zoom, feature, canonicalID);
|
||||
const float layoutIconSize = layout->evaluate<IconSize>(zoom + 1, feature, canonicalID);
|
||||
|
||||
// if feature has text, shape the text
|
||||
if (feature.formattedText && layoutTextSize > 0.0f) {
|
||||
const float lineHeight = layout->get<TextLineHeight>() * util::ONE_EM;
|
||||
const float spacing = util::i18n::allowsLetterSpacing(feature.formattedText->rawText()) ? layout->evaluate<TextLetterSpacing>(zoom, feature) * util::ONE_EM : 0.0f;
|
||||
const float spacing = util::i18n::allowsLetterSpacing(feature.formattedText->rawText())
|
||||
? layout->evaluate<TextLetterSpacing>(zoom, feature, canonicalID) * util::ONE_EM
|
||||
: 0.0f;
|
||||
|
||||
auto applyShaping = [&](const TaggedString& formattedText,
|
||||
WritingModeType writingMode,
|
||||
@@ -371,7 +374,7 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap,
|
||||
const Shaping result = getShaping(
|
||||
/* string */ formattedText,
|
||||
/* maxWidth: ems */
|
||||
isPointPlacement ? layout->evaluate<TextMaxWidth>(zoom, feature) * util::ONE_EM : 0.0f,
|
||||
isPointPlacement ? layout->evaluate<TextMaxWidth>(zoom, feature, canonicalID) * util::ONE_EM : 0.0f,
|
||||
/* ems */ lineHeight,
|
||||
textAnchor,
|
||||
textJustify,
|
||||
@@ -389,22 +392,24 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap,
|
||||
return result;
|
||||
};
|
||||
|
||||
const std::vector<style::TextVariableAnchorType> variableTextAnchor = layout->evaluate<TextVariableAnchor>(zoom, feature);
|
||||
const SymbolAnchorType textAnchor = layout->evaluate<TextAnchor>(zoom, feature);
|
||||
const std::vector<style::TextVariableAnchorType> variableTextAnchor =
|
||||
layout->evaluate<TextVariableAnchor>(zoom, feature, canonicalID);
|
||||
const SymbolAnchorType textAnchor = layout->evaluate<TextAnchor>(zoom, feature, canonicalID);
|
||||
if (variableTextAnchor.empty()) {
|
||||
// Layers with variable anchors use the `text-radial-offset` property and the [x, y] offset vector
|
||||
// is calculated at placement time instead of layout time
|
||||
const float radialOffset = layout->evaluate<TextRadialOffset>(zoom, feature);
|
||||
const float radialOffset = layout->evaluate<TextRadialOffset>(zoom, feature, canonicalID);
|
||||
if (radialOffset > 0.0f) {
|
||||
// The style spec says don't use `text-offset` and `text-radial-offset` together
|
||||
// but doesn't actually specify what happens if you use both. We go with the radial offset.
|
||||
textOffset = evaluateRadialOffset(textAnchor, radialOffset * util::ONE_EM);
|
||||
} else {
|
||||
textOffset = {{layout->evaluate<TextOffset>(zoom, feature)[0] * util::ONE_EM,
|
||||
layout->evaluate<TextOffset>(zoom, feature)[1] * util::ONE_EM}};
|
||||
textOffset = {{layout->evaluate<TextOffset>(zoom, feature, canonicalID)[0] * util::ONE_EM,
|
||||
layout->evaluate<TextOffset>(zoom, feature, canonicalID)[1] * util::ONE_EM}};
|
||||
}
|
||||
}
|
||||
TextJustifyType textJustify = textAlongLine ? TextJustifyType::Center : layout->evaluate<TextJustify>(zoom, feature);
|
||||
TextJustifyType textJustify =
|
||||
textAlongLine ? TextJustifyType::Center : layout->evaluate<TextJustify>(zoom, feature, canonicalID);
|
||||
|
||||
const auto addVerticalShapingForPointLabelIfNeeded = [&] {
|
||||
if (allowVerticalPlacement && feature.formattedText->allowsVerticalWritingMode()) {
|
||||
@@ -474,8 +479,8 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap,
|
||||
if (image != imageMap.end()) {
|
||||
iconType = SymbolContent::IconRGBA;
|
||||
shapedIcon = PositionedIcon::shapeIcon(imagePositions.at(feature.icon->id()),
|
||||
layout->evaluate<IconOffset>(zoom, feature),
|
||||
layout->evaluate<IconAnchor>(zoom, feature));
|
||||
layout->evaluate<IconOffset>(zoom, feature, canonicalID),
|
||||
layout->evaluate<IconAnchor>(zoom, feature, canonicalID));
|
||||
if (image->second->sdf) {
|
||||
iconType = SymbolContent::IconSDF;
|
||||
}
|
||||
@@ -520,13 +525,13 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
|
||||
const float minScale = 0.5f;
|
||||
const float glyphSize = 24.0f;
|
||||
|
||||
const std::array<float, 2> iconOffset = layout->evaluate<IconOffset>(zoom, feature);
|
||||
const std::array<float, 2> iconOffset = layout->evaluate<IconOffset>(zoom, feature, canonicalID);
|
||||
|
||||
// To reduce the number of labels that jump around when zooming we need
|
||||
// to use a text-size value that is the same for all zoom levels.
|
||||
// This calculates text-size at a high zoom level so that all tiles can
|
||||
// use the same value when calculating anchor positions.
|
||||
const float textMaxSize = layout->evaluate<TextSize>(18, feature);
|
||||
const float textMaxSize = layout->evaluate<TextSize>(18, feature, canonicalID);
|
||||
|
||||
const float fontScale = layoutTextSize / glyphSize;
|
||||
const float textBoxScale = tilePixelRatio * fontScale;
|
||||
@@ -536,15 +541,15 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex,
|
||||
const float textPadding = layout->get<TextPadding>() * tilePixelRatio;
|
||||
const float iconPadding = layout->get<IconPadding>() * tilePixelRatio;
|
||||
const float textMaxAngle = layout->get<TextMaxAngle>() * util::DEG2RAD;
|
||||
const float iconRotation = layout->evaluate<IconRotate>(zoom, feature);
|
||||
const float textRotation = layout->evaluate<TextRotate>(zoom, feature);
|
||||
const float iconRotation = layout->evaluate<IconRotate>(zoom, feature, canonicalID);
|
||||
const float textRotation = layout->evaluate<TextRotate>(zoom, feature, canonicalID);
|
||||
std::array<float, 2> variableTextOffset;
|
||||
if (!textRadialOffset.isUndefined()) {
|
||||
variableTextOffset = {{layout->evaluate<TextRadialOffset>(zoom, feature) * util::ONE_EM,
|
||||
INVALID_OFFSET_VALUE}};
|
||||
variableTextOffset = {
|
||||
{layout->evaluate<TextRadialOffset>(zoom, feature, canonicalID) * util::ONE_EM, INVALID_OFFSET_VALUE}};
|
||||
} else {
|
||||
variableTextOffset = {{layout->evaluate<TextOffset>(zoom, feature)[0] * util::ONE_EM,
|
||||
layout->evaluate<TextOffset>(zoom, feature)[1] * util::ONE_EM}};
|
||||
variableTextOffset = {{layout->evaluate<TextOffset>(zoom, feature, canonicalID)[0] * util::ONE_EM,
|
||||
layout->evaluate<TextOffset>(zoom, feature, canonicalID)[1] * util::ONE_EM}};
|
||||
}
|
||||
|
||||
const SymbolPlacementType textPlacement = layout->get<TextRotationAlignment>() != AlignmentType::Map
|
||||
|
||||
@@ -115,6 +115,7 @@ private:
|
||||
const std::unique_ptr<GeometryTileLayer> sourceLayer;
|
||||
const float overscaling;
|
||||
const float zoom;
|
||||
const CanonicalTileID canonicalID;
|
||||
const MapMode mode;
|
||||
const float pixelRatio;
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ void FillBucket::addFeature(const GeometryTileFeature& feature,
|
||||
|
||||
for (auto& pair : paintPropertyBinders) {
|
||||
const auto it = patternDependencies.find(pair.first);
|
||||
if (it != patternDependencies.end()){
|
||||
if (it != patternDependencies.end()) {
|
||||
pair.second.populateVertexVectors(
|
||||
feature, vertices.elements(), index, patternPositions, it->second, canonical);
|
||||
} else {
|
||||
|
||||
@@ -34,7 +34,7 @@ void LineBucket::addFeature(const GeometryTileFeature& feature,
|
||||
std::size_t index,
|
||||
const CanonicalTileID& canonical) {
|
||||
for (auto& line : geometryCollection) {
|
||||
addGeometry(line, feature);
|
||||
addGeometry(line, feature, canonical);
|
||||
}
|
||||
|
||||
for (auto& pair : paintPropertyBinders) {
|
||||
@@ -97,7 +97,9 @@ private:
|
||||
double total;
|
||||
};
|
||||
|
||||
void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const GeometryTileFeature& feature) {
|
||||
void LineBucket::addGeometry(const GeometryCoordinates& coordinates,
|
||||
const GeometryTileFeature& feature,
|
||||
const CanonicalTileID& canonical) {
|
||||
const FeatureType type = feature.getType();
|
||||
const std::size_t len = [&coordinates] {
|
||||
std::size_t l = coordinates.size();
|
||||
@@ -137,7 +139,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, const Geome
|
||||
*numericValue<double>(clip_start_it->second), *numericValue<double>(clip_end_it->second), total_length};
|
||||
}
|
||||
|
||||
const LineJoinType joinType = layout.evaluate<LineJoin>(zoom, feature);
|
||||
const LineJoinType joinType = layout.evaluate<LineJoin>(zoom, feature, canonical);
|
||||
|
||||
const float miterLimit = joinType == LineJoinType::Bevel ? 1.05f : float(layout.get<LineMiterLimit>());
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
std::map<std::string, LineProgram::Binders> paintPropertyBinders;
|
||||
|
||||
private:
|
||||
void addGeometry(const GeometryCoordinates&, const GeometryTileFeature&);
|
||||
void addGeometry(const GeometryCoordinates&, const GeometryTileFeature&, const CanonicalTileID&);
|
||||
|
||||
struct TriangleElement {
|
||||
TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {}
|
||||
|
||||
@@ -50,6 +50,14 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
template <class Feature>
|
||||
T evaluate(const Feature& feature, float zoom, const CanonicalTileID& canonical, T defaultValue) const {
|
||||
return this->match([&](const T& constant_) { return constant_; },
|
||||
[&](const style::PropertyExpression<T>& expression) {
|
||||
return expression.evaluate(zoom, feature, canonical, defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
template <class Feature>
|
||||
T evaluate(const Feature& feature, float zoom, const FeatureState& featureState, T defaultValue) const {
|
||||
return this->match([&](const T& constant_) { return constant_; },
|
||||
@@ -96,13 +104,15 @@ public:
|
||||
Faded<T> evaluate(const Feature& feature,
|
||||
float zoom,
|
||||
const std::set<std::string>& availableImages,
|
||||
const CanonicalTileID& canonical,
|
||||
T defaultValue) const {
|
||||
return this->match(
|
||||
[&] (const Faded<T>& constant_) { return constant_; },
|
||||
[&] (const style::PropertyExpression<T>& expression) {
|
||||
if (!expression.isZoomConstant()) {
|
||||
const T min = expression.evaluate(floor(zoom), feature, availableImages, defaultValue);
|
||||
const T max = expression.evaluate(floor(zoom) + 1, feature, availableImages, defaultValue);
|
||||
const T min = expression.evaluate(floor(zoom), feature, availableImages, canonical, defaultValue);
|
||||
const T max =
|
||||
expression.evaluate(floor(zoom) + 1, feature, availableImages, canonical, defaultValue);
|
||||
return Faded<T> {min, max};
|
||||
} else {
|
||||
const T evaluated = expression.evaluate(feature, availableImages, defaultValue);
|
||||
|
||||
@@ -168,6 +168,11 @@ public:
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float, const GeometryTileFeature&, const CanonicalTileID&, const T& t, const T&) {
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float z,
|
||||
const GeometryTileFeature& feature,
|
||||
@@ -193,6 +198,30 @@ public:
|
||||
[&](const PropertyExpression<T>& t) { return t.evaluate(z, feature, availableImages, defaultValue); });
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float z,
|
||||
const GeometryTileFeature& feature,
|
||||
const PossiblyEvaluatedPropertyValue<T>& v,
|
||||
const T& defaultValue,
|
||||
const std::set<std::string>& availableImages,
|
||||
const CanonicalTileID& canonical) {
|
||||
return v.match([&](const T& t) { return t; },
|
||||
[&](const PropertyExpression<T>& t) {
|
||||
return t.evaluate(z, feature, availableImages, canonical, defaultValue);
|
||||
});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float z,
|
||||
const GeometryTileFeature& feature,
|
||||
const CanonicalTileID& canonical,
|
||||
const PossiblyEvaluatedPropertyValue<T>& v,
|
||||
const T& defaultValue) {
|
||||
return v.match(
|
||||
[&](const T& t) { return t; },
|
||||
[&](const PropertyExpression<T>& t) { return t.evaluate(z, feature, canonical, defaultValue); });
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T evaluate(float z, const GeometryTileFeature& feature, const FeatureState& state,
|
||||
const PossiblyEvaluatedPropertyValue<T>& v, const T& defaultValue) {
|
||||
@@ -220,6 +249,14 @@ public:
|
||||
return evaluate(z, feature, this->template get<P>(), P::defaultValue(), availableImages);
|
||||
}
|
||||
|
||||
template <class P>
|
||||
auto evaluate(float z,
|
||||
const GeometryTileFeature& feature,
|
||||
const std::set<std::string>& availableImages,
|
||||
const CanonicalTileID& canonical) const {
|
||||
return evaluate(z, feature, this->template get<P>(), P::defaultValue(), availableImages, canonical);
|
||||
}
|
||||
|
||||
Evaluated evaluate(float z, const GeometryTileFeature& feature) const {
|
||||
return Evaluated {
|
||||
evaluate<Ps>(z, feature)...
|
||||
|
||||
Reference in New Issue
Block a user