#pragma once #include #include #include #include #include #include #include namespace mbgl { namespace style { template class PropertyExpression { public: // Second parameter to be used only for conversions from legacy functions. PropertyExpression(std::unique_ptr expression_, optional defaultValue_ = {}) : expression(std::move(expression_)), defaultValue(std::move(defaultValue_)), zoomCurve(expression::findZoomCurveChecked(expression.get())) { } bool isZoomConstant() const { return expression::isZoomConstant(*expression); } bool isFeatureConstant() const { return expression::isFeatureConstant(*expression); } T evaluate(float zoom) const { assert(!expression::isZoomConstant(*expression)); assert(expression::isFeatureConstant(*expression)); const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(zoom, nullptr)); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : T(); } return defaultValue ? *defaultValue : T(); } template T evaluate(const Feature& feature, T finalDefaultValue) const { assert(expression::isZoomConstant(*expression)); assert(!expression::isFeatureConstant(*expression)); const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext(&feature)); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue; } return defaultValue ? *defaultValue : finalDefaultValue; } template T evaluate(float zoom, const Feature& feature, T finalDefaultValue) const { assert(!expression::isFeatureConstant(*expression)); const expression::EvaluationResult result = expression->evaluate(expression::EvaluationContext({zoom}, &feature)); if (result) { const optional typed = expression::fromExpressionValue(*result); return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue; } return defaultValue ? *defaultValue : finalDefaultValue; } float interpolationFactor(const Range& inputLevels, const float inputValue) const { return zoomCurve.match( [](std::nullptr_t) { assert(false); return 0.0f; }, [&](const expression::Interpolate* z) { return z->interpolationFactor(Range { inputLevels.min, inputLevels.max }, inputValue); }, [&](const expression::Step*) { return 0.0f; } ); } Range getCoveringStops(const float lower, const float upper) const { return zoomCurve.match( [](std::nullptr_t) { assert(false); return Range(0.0f, 0.0f); }, [&](auto z) { return z->getCoveringStops(lower, upper); } ); } // Return the range obtained by evaluating the function at each of the zoom levels in zoomRange template Range evaluate(const Range& zoomRange, const Feature& feature, T finalDefaultValue) { return Range { evaluate(zoomRange.min, feature, finalDefaultValue), evaluate(zoomRange.max, feature, finalDefaultValue) }; } std::vector> possibleOutputs() const { return expression::fromExpressionValues(expression->possibleOutputs()); } const expression::Expression& getExpression() const { return *expression; } bool useIntegerZoom = false; friend bool operator==(const PropertyExpression& lhs, const PropertyExpression& rhs) { return *lhs.expression == *rhs.expression; } private: std::shared_ptr expression; optional defaultValue; variant zoomCurve; }; } // namespace style } // namespace mbgl