#pragma once #include #include #include #include #include #include namespace mbgl { namespace style { class PropertyExpressionBase { public: explicit PropertyExpressionBase(std::unique_ptr); bool isZoomConstant() const noexcept; bool isFeatureConstant() const noexcept; bool isRuntimeConstant() const noexcept; float interpolationFactor(const Range&, float) const noexcept; Range getCoveringStops(float, float) const noexcept; const expression::Expression& getExpression() const noexcept; // Can be used for aggregating property expressions from multiple // properties(layers) into single match / case expression. Method may // be removed if a better way of aggregation is found. std::shared_ptr getSharedExpression() const noexcept; bool useIntegerZoom = false; protected: std::shared_ptr expression; variant zoomCurve; bool isZoomConstant_; bool isFeatureConstant_; bool isRuntimeConstant_; }; template class PropertyExpression final : public PropertyExpressionBase { public: // Second parameter to be used only for conversions from legacy functions. PropertyExpression(std::unique_ptr expression_, optional defaultValue_ = nullopt) : PropertyExpressionBase(std::move(expression_)), defaultValue(std::move(defaultValue_)) { } T evaluate(const expression::EvaluationContext& context, T finalDefaultValue = T()) const { const expression::EvaluationResult result = expression->evaluate(context); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue; } return defaultValue ? *defaultValue : finalDefaultValue; } T evaluate(float zoom) const { assert(!isZoomConstant()); assert(isFeatureConstant()); return evaluate(expression::EvaluationContext(zoom)); } T evaluate(const GeometryTileFeature& feature, T finalDefaultValue) const { assert(isZoomConstant()); assert(!isFeatureConstant()); return evaluate(expression::EvaluationContext(&feature), finalDefaultValue); } T evaluate(const GeometryTileFeature& feature, const std::set& availableImages, T finalDefaultValue) const { return evaluate(expression::EvaluationContext(&feature).withAvailableImages(&availableImages), 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& 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); } T evaluate(float zoom, const GeometryTileFeature& feature, const std::set& availableImages, T finalDefaultValue) const { return evaluate(expression::EvaluationContext(zoom, &feature).withAvailableImages(&availableImages), finalDefaultValue); } T evaluate(float zoom, const GeometryTileFeature& feature, const std::set& 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); } std::vector> possibleOutputs() const { return expression::fromExpressionValues(expression->possibleOutputs()); } friend bool operator==(const PropertyExpression& lhs, const PropertyExpression& rhs) { return *lhs.expression == *rhs.expression; } private: optional defaultValue; }; } // namespace style } // namespace mbgl