summaryrefslogtreecommitdiff
path: root/include/mbgl/style/property_expression.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl/style/property_expression.hpp')
-rw-r--r--include/mbgl/style/property_expression.hpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/include/mbgl/style/property_expression.hpp b/include/mbgl/style/property_expression.hpp
new file mode 100644
index 0000000000..16f154cdf2
--- /dev/null
+++ b/include/mbgl/style/property_expression.hpp
@@ -0,0 +1,125 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/is_constant.hpp>
+#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/step.hpp>
+#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/util/range.hpp>
+
+namespace mbgl {
+namespace style {
+
+template <class T>
+class PropertyExpression {
+public:
+ PropertyExpression(std::unique_ptr<expression::Expression> expression_)
+ : isExpression(true),
+ expression(std::move(expression_)),
+ zoomCurve(expression::findZoomCurveChecked(expression.get())) {
+ }
+
+ // To be used only for conversions from legacy functions.
+ PropertyExpression(std::unique_ptr<expression::Expression> expression_, optional<T> defaultValue_)
+ : isExpression(false),
+ 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<T> typed = expression::fromExpressionValue<T>(*result);
+ return typed ? *typed : defaultValue ? *defaultValue : T();
+ }
+ return defaultValue ? *defaultValue : T();
+ }
+
+ template <class Feature>
+ 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<T> typed = expression::fromExpressionValue<T>(*result);
+ return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
+ }
+ return defaultValue ? *defaultValue : finalDefaultValue;
+ }
+
+ template <class Feature>
+ 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<T> typed = expression::fromExpressionValue<T>(*result);
+ return typed ? *typed : defaultValue ? *defaultValue : finalDefaultValue;
+ }
+ return defaultValue ? *defaultValue : finalDefaultValue;
+ }
+
+ float interpolationFactor(const Range<float>& inputLevels, const float inputValue) const {
+ return zoomCurve.match(
+ [](std::nullptr_t) {
+ assert(false);
+ return 0.0f;
+ },
+ [&](const expression::Interpolate* z) {
+ return z->interpolationFactor(Range<double> { inputLevels.min, inputLevels.max }, inputValue);
+ },
+ [&](const expression::Step*) {
+ return 0.0f;
+ }
+ );
+ }
+
+ Range<float> getCoveringStops(const float lower, const float upper) const {
+ return zoomCurve.match(
+ [](std::nullptr_t) {
+ assert(false);
+ return Range<float>(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 <class Feature>
+ Range<T> evaluate(const Range<float>& zoomRange, const Feature& feature, T finalDefaultValue) {
+ return Range<T> {
+ evaluate(zoomRange.min, feature, finalDefaultValue),
+ evaluate(zoomRange.max, feature, finalDefaultValue)
+ };
+ }
+
+ std::vector<optional<T>> possibleOutputs() const {
+ return expression::fromExpressionValues<T>(expression->possibleOutputs());
+ }
+
+ const expression::Expression& getExpression() const { return *expression; }
+
+ bool useIntegerZoom = false;
+ bool isExpression;
+
+ friend bool operator==(const PropertyExpression& lhs,
+ const PropertyExpression& rhs) {
+ return *lhs.expression == *rhs.expression;
+ }
+
+private:
+ std::shared_ptr<const expression::Expression> expression;
+ optional<T> defaultValue;
+ variant<std::nullptr_t, const expression::Interpolate*, const expression::Step*> zoomCurve;
+};
+
+} // namespace style
+} // namespace mbgl